我一直百思不得其解解决此问题在MySQL的5.0.51a现在相当长的一段:在mysql LEFT不使用索引联接WHERE子句
当使用LEFT JOIN加入一个表,并使用WHERE子句中连接表的列,mySQL无法使用JOIN中连接表的主索引,即使FORCE INDEX(PRIMARY)也失败。
- 如果未连接的表的列在WHERE子句中,则一切正常。
- 如果删除GROUP BY,则也使用该索引。
但我需要他们两个。
故障: (的EXEC时间在我的特殊情况下可达1000秒)
SELECT *
FROM tbl_contract co
LEFT JOIN tbl_customer cu ON cu.customer_id = co.customer_id
WHERE cu.marketing_allowed = 1 AND co.marketing_allowed = 1
GROUP BY cu.id
ORDER BY cu.name ASC
工作,但没有解决我的问题:
SELECT *
FROM tbl_contract co
LEFT JOIN tbl_customer cu ON cu.customer_id = co.customer_id
GROUP BY co.id
表结构(转录,作为真正的表更复杂)
tbl_contract:
id: INT(11) PRIMARY
customer_id: INT(11)
marketing_allowed: TINYINT(1)
tbl_customer:
customer_id: INT(11) PRIMARY
marketing_allowed: TINYINT(1)
mySQL EXPLAIN通知PRIMARY作为可能的键加入时,但不使用它。
已经有一个解决办法:
SELECT (...)
HAVING cu.marketing_allowed = 1
解决了但我们使用的查询在其他情况下,我们只能选择在整个声明中一列问题,但有需求的marketing_allowed列在SELECT语句中被选中。
我也注意到,在所需的表上运行ANALYZE TABLE将会使mySQL 5.5.8在我的本地系统上做正确的事情,但我不能始终确保ANALYZE已经在语句前运行。无论如何,这个解决方案在我们的生产服务器上不能在mySQL 5.0.51a下运行。 :(
有MySQL中的特殊规则,我没注意到?为什么LEFT JOIN不使用索引,如果列显示在WHERE子句中?为什么我不能强迫他们?提前
THX ,
勒
[编辑]
由于一些答复,我可以用一个订单时使用INNER JOIN优化查询,但遗憾的是,虽然看似精绝,MySQL的仍然拒绝使用索引BY条款,正如我发现的那样:
SELECT *
FROM tbl_contract co
INNER JOIN tbl_customer cu ON cu.customer_id = co.customer_id AND cu.marketing_allowed = 1
WHERE cu.marketing_allowed = 1
ORDER BY cu.name ASC
如果您离开ORDER BY,mySQL将正确使用索引。 我已经删除了GROUP BY,因为它在示例中没有相关性。
[编辑2]
FORCING索引也没有帮助。所以,问题是:为什么mySQL不使用索引进行连接,因为在连接和减少WHERE子句的结果集之后执行ORDER BY?这通常不应该影响加入...
你怎么知道“mySQL无法使用主索引”?你检查过'EXPLAIN'的输出吗?你能把它包括在你的问题中吗? – eggyal
请分享表格结构。 –
嗨,是的,我大量使用了EXPLAIN,午餐休息后我会修改我的请求;) –