我有一个MySQL数据库,其中表A与表B具有一对多关系,我想选择表B中表A中没有子项的所有行。- X. n" _ l' q' i
SELECT id FROM A WHERE NOT EXISTS (SELECT * FROM B WHERE B.id=A.id)2 V5 i( Y% Y9 l9 q7 `4 H- T, u
和9 j" ~' \) L7 N) k+ e! s6 d
SELECT id FROM A LEFT JOIN B ON A.id=B.id WHERE B.id IS NULL- m4 K+ k3 f8 M% z$ s u8 s; p$ e; R
两者似乎都很慢。是否有更快的查询来实现相同的目的?! M4 b( E7 u7 _# y* }. @
如果这是相关的,在我的数据库中,表A大约有500,000行,表B大约有3到4百万行。# P0 n' q' H. t: s 编辑: 对于我的数据库中的实际表,解释给我: $ X) X" X# E) O: ?4 |* d+----+--------------------+------------------+-------+---------------+---------------------------+---------+------+---------+--------------------------+' G) H( l8 k/ D
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |% f6 {1 X9 E' j# w3 [* R) R
+----+--------------------+------------------+-------+---------------+---------------------------+---------+------+---------+--------------------------+% ~" J& G- k/ p+ l. E+ D( P. _5 f
| 1 | PRIMARY | frontend_form471 | index | NULL | frontend_form471_61a633e8 | 32 | NULL | 671927 | Using where; Using index |# z$ ]# H. C, a4 t$ \; c
| 2 | DEPENDENT SUBQUERY | SchoolData | index | PRIMARY | PRIMARY | 49 | NULL | 3121110 | Using where; Using index | # B) v I. A/ x4 \; K+----+--------------------+------------------+-------+---------------+---------------------------+---------+------+---------+--------------------------+ & h N7 P2 I) n( X3 p为了 4 D9 c x* r* Q6 a0 Q; }: J( cselect number from frontend_form471 where not exists (select * from SchoolData where SchoolData.`f471 Application Number`=frontend_form471.number) * ]4 c2 A$ x$ G7 f8 Y, u和4 _! C+ n7 \1 Y
+----+-------------+------------------+-------+---------------+---------------------------+---------+------+---------+------------------------------------------------+) y! R# p# ]1 _. U
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | / j* U6 E8 a& b( k8 Y+----+-------------+------------------+-------+---------------+---------------------------+---------+------+---------+------------------------------------------------+ # q# B1 |" b* ], || 1 | SIMPLE | frontend_form471 | index | NULL | frontend_form471_61a633e8 | 32 | NULL | 671927 | Using index; Using temporary |! }8 [" _3 M( @; v" Z
| 1 | SIMPLE | SchoolData | index | PRIMARY | PRIMARY | 49 | NULL | 3121110 | Using where; Using index; Not exists; Distinct | + P- t% h# X X4 _5 `* i7 O+----+-------------+------------------+-------+---------------+---------------------------+---------+------+---------+------------------------------------------------+# S4 S* w# @3 x, y5 C
为了! p, s1 T2 m: A3 v; q+ ]" `
select distinct number from frontend_form471 left join SchoolData on frontend_form471.number=SchoolData.`f471 Application Number` where SchoolData.`f471 Application Number` is NULL2 b0 v J" g( S9 P1 H5 V; y
在我的情况下,frontend_form471是表A,SchoolData是表B # m3 T' H# D( Y/ K, mEdit2: 在我数据库的表B(SchoolData)中,id是两部分主键的第一部分,因此已对其进行了索引,并且B中仍然存在多个具有相同id的条目。 % E; s% T3 k0 ^1 u 1 C7 t$ Z" m+ x9 g" A 解决方案: 8 x- v9 t# _0 C- y% u2 T Q # n; g/ Q7 O4 @' G0 U6 d! P' q* u B1 |: d
5 I! Q6 p+ U! w" E/ K
SELECT id FROM A LEFT OUTER JOIN B ON A.id=B.id WHERE B.id IS NULL2 G; g' B$ F9 z& U( N& n
你可以这样做。外部联接应该带来一点性能,但不是很多。5 ]6 {9 Q) r* Z" n) t
新的数据库系统可能仍会优化您的查询,因此不会有任何差异。" N. }1 V- c. ~2 T& X- H- a
正确的方法是缓存!如果可能,请尝试查询缓存和应用程序级缓存。, |+ N6 l1 r- |# V
当然,您需要适当的索引。6 a) b/ ]8 {) i: g
正确地说,我的意思是在两个表上最好是一个哈希索引,因为与具有对数的任何树相比,它具有静态查找时间 6 j' o+ i" S8 x' o尝试在查询前放置一个解释,以了解到底是什么使速度变慢了。7 Z- E' N/ S N: ?2 E
如果您确实需要此方法来加快速度,则可以重新构建数据结构。* @5 G( B0 F% X/ a9 \9 `% W
您可以创建一个触发器来标记表A中的标志,表be中是否存在相应的条目。当然,这种id数据冗余,但有时值得。只是将其视为缓存。& L) }) h/ L& l9 @& b1 q3 m
最后一个想法:您可以尝试SELECT id FROM A WHERE id NOT IN (SELECT id FROM 4 @" u9 c, p! \& |" [3 [8 u8 `- RB)这样做可能会更快一些,因为不需要实际的连接,但是它也可能会比较慢,因为在be集合中的查找将是一次完整扫描。我不确定该如何处理,但值得一试。