我知道我可以使用FORCE INDEX (abc)
关键字更改MySQL执行查询的方式。但有没有办法改变执行顺序?
我的查询如下:
SELECT c.*
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1_id
INNER JOIN table3 c ON b.itemid = c.itemid
WHERE a.itemtype = 1
AND a.busy = 1
AND b.something = 0
AND b.acolumn = 2
AND c.itemid = 123456
我有一个用于我使用的每个关系/约束的键。如果我在这个语句上运行解释,我看到mysql首先开始查询c。
id select_type table type
1 SIMPLE c ref
2 SIMPLE b ref
3 SIMPLE a eq_ref
但是,我知道按a -> b -> c
顺序查询会更快(我已经证明了这一点)
有没有办法告诉mysql使用特定的订单?
更新:我知道a -> b -> c
更快。
上述查询需要1.9秒才能完成并返回7行。如果我将查询更改为
SELECT c.*
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1_id
INNER JOIN table3 c ON b.itemid = c.itemid
WHERE a.itemtype = 1
AND a.busy = 1
AND b.something = 0
AND b.acolumn = 2
HAVING c.itemid = 123456
查询在0.01秒内完成(不使用我获得10.000行)。
然而,这不是一个优雅的解决方案,因为此查询是一个简化的示例。在现实世界中,我从c加入到其他表中。由于HAVING
是一个在整个结果上执行的过滤器,因此我意味着我会从数据库中提取更多的记录而不是nescessary。
Edit2:只是一些信息:
关键是mysql应该开始查询表a并将其工作到c而不是反过来。对此有任何改变。
解决方案:不完全是我想要的,但这似乎有效:
SELECT c.*
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1_id
INNER JOIN table3 c ON b.itemid = c.itemid
WHERE a.itemtype = 1
AND a.busy = 1
AND b.something = 0
AND b.acolumn = 2
AND c.itemid = 123456
AND f.id IN (
SELECT DISTINCT table2.id FROM table1
INNER JOIN table2 ON table1.id = table2.table1_id
WHERE table1.itemtype = 1 AND table1.busy = 1)
答案 0 :(得分:35)
也许你需要使用STRAIGHT_JOIN
。
http://dev.mysql.com/doc/refman/5.0/en/join.html
STRAIGHT_JOIN
与JOIN
类似,只是左表始终在右表之前读取。这可以用于连接优化器以错误顺序放置表的那些(少数)情况。
答案 1 :(得分:3)
答案 2 :(得分:3)
您可以使用FORCE INDEX强制执行命令,我之前已经这样做了。
如果您考虑一下,通常只有一个订单可以查询您选择的任何索引的表格。
在这种情况下,如果您希望MySQL首先开始查询a
,请确保您在b
上强制使用的索引是包含b.table1_id
的索引。如果已经首先查询a
,MySQL将只能使用该索引。