我正在试图找出为什么这个查询如此缓慢(大约需要6秒才能得到结果)
SELECT DISTINCT
c.id
FROM
z1
INNER JOIN
c ON (z1.id = c.id)
INNER JOIN
i ON (c.member_id = i.member_id)
WHERE
c.id NOT IN (... big list of ids which should be excluded)
这是执行计划
+----+-------------+-------+--------+-------------------+---------+---------+--------------------+--------+----------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+--------+-------------------+---------+---------+--------------------+--------+----------+--------------------------+
| 1 | SIMPLE | z1 | index | PRIMARY | PRIMARY | 4 | NULL | 318563 | 99.85 | Using where; Using index; Using temporary |
| 1 | SIMPLE | c | eq_ref | PRIMARY,member_id | PRIMARY | 4 | z1.id | 1 | 100.00 | |
| 1 | SIMPLE | i | eq_ref | PRIMARY | PRIMARY | 4 | c.member_id | 1 | 100.00 | Using index |
+----+-------------+-------+--------+-------------------+---------+---------+--------------------+--------+----------+--------------------------+
是不是因为mysql几乎要拿掉整个第一张桌子?可以调整吗?
答案 0 :(得分:1)
您可以尝试用子查询替换c。
SELECT DISTINCT
c.id
FROM
z1
INNER JOIN
(select c.id
from c
WHERE
c.id NOT IN (... big list of ids which should be excluded)) c ON (z1.id = c.id)
INNER JOIN
i ON (c.member_id = i.member_id)
只留下必要的id
答案 1 :(得分:1)
根据您提供的信息说,是否有更快的解决方案来获取相同的数据是不可能的(我们需要知道数据分布以及必须使用哪些外键)。但是假设这是一个分层数据集,那么该计划可能不是最优的:减少行数的唯一谓词是c.id NOT IN....
。
在优化任何查询时要问自己的第一个问题是我是否需要所有行?这回来了多少行?
我很难在查询中看到任何返回“id”值列表(表示一组自动增量整数)的信息。
你不能使用NOT IN(或&lt;&gt;)的索引,因此最有效的解决方案可能是从'c'开始全表扫描 - 这应该是StanislavL查询的结果。< / p>
由于您不使用i和z中的值,因此连接可以替换为“exists”,可以帮助提高性能。
答案 2 :(得分:0)
我会考虑为c(id, member_id)
创建复合索引。这样查询应该只在索引级别工作,而不扫描表中的任何行。