我有一个MySQL数据库,其中表A与表B有一对多的关系,我想选择表B中表A中没有子项的所有行.我试过使用
SELECT id FROM A WHERE NOT EXISTS (SELECT * FROM B WHERE B.id=A.id)
Run Code Online (Sandbox Code Playgroud)
和
SELECT id FROM A LEFT JOIN B ON A.id=B.id WHERE B.id IS NULL
Run Code Online (Sandbox Code Playgroud)
这两个似乎都很慢.是否有更快的查询来实现同样的事情?
如果这是相关的,在我的数据库表A中有大约500,000行,而表B有大约3到4百万行.
编辑:对于我数据库中的实际表,解释给了我:
+----+--------------------+------------------+-------+---------------+---------------------------+---------+------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------------+-------+---------------+---------------------------+---------+------+---------+--------------------------+
| 1 | PRIMARY | frontend_form471 | index | NULL | frontend_form471_61a633e8 | 32 | NULL | 671927 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | SchoolData | index | PRIMARY | PRIMARY | 49 | NULL | 3121110 | Using where; Using index |
+----+--------------------+------------------+-------+---------------+---------------------------+---------+------+---------+--------------------------+
Run Code Online (Sandbox Code Playgroud)
对于
select number from frontend_form471 where not exists (select * from SchoolData where SchoolData.`f471 Application Number`=frontend_form471.number)
Run Code Online (Sandbox Code Playgroud)
和
+----+-------------+------------------+-------+---------------+---------------------------+---------+------+---------+------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------+-------+---------------+---------------------------+---------+------+---------+------------------------------------------------+
| 1 | SIMPLE | frontend_form471 | index | NULL | frontend_form471_61a633e8 | 32 | NULL | 671927 | Using index; Using temporary |
| 1 | SIMPLE | SchoolData | index | PRIMARY | PRIMARY | 49 | NULL | 3121110 | Using where; Using index; Not exists; Distinct |
+----+-------------+------------------+-------+---------------+---------------------------+---------+------+---------+------------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
对于
select distinct number from frontend_form471 left join SchoolData on frontend_form471.number=SchoolData.`f471 Application Number` where SchoolData.`f471 Application Number` is NULL
Run Code Online (Sandbox Code Playgroud)
在我的情况下,frontend_form471是表A,而SchoolData是表B.
Edit2:在我的数据库中的表B(SchoolData)中,id是两部分主键的第一部分,因此它被编入索引,并且B中仍有多个具有相同id的条目.
SELECT id FROM A LEFT OUTER JOIN B ON A.id=B.id WHERE B.id IS NULL
Run Code Online (Sandbox Code Playgroud)
你可以这样做.外连接应该带来一点性能,但不是很多.
无论如何,新的数据库系统可能会优化您的查询,以便不会有任何区别.
这里正确的方法是缓存!如果可能,尝试查询cacher和应用程序级缓存.
当然你需要适当的索引.
并且恰当地意思是在两个表上并且优选地是哈希索引,因为它将具有与具有对数的任何树的比较的静态查找时间
尝试在查询之前添加一个解释,看看真正减慢了什么.
如果你真的需要这么快,你可能会重新制定你的数据结构.
您可以创建一个触发器来标记表A中的标志,表中是否有相应的条目.当然这个id数据冗余,但有时它值得.把它想象成缓存.
最后一个想法:你可以尝试SELECT id FROM A WHERE id NOT IN (SELECT id FROM B)它可能会更快一点,因为不需要实际连接,但它也可能更慢,因为在集合中的查找将是一个完整的扫描.我不确定这将如何处理,但它可能值得一试.