我有两张桌子
表X:百万或记录
|-----|-----|-----|-----|
| a | b | c | d |
|-----|-----|-----|-----|
表Y:仅几条记录
|-----|-----|
| e | f |
|-----|-----|
X.d
允许我加入两个表 X.d = Y.e
我有以下索引:
我们的应用程序之一正在执行以下查询,该查询需要花一些时间才能运行:
SELECT *
FROM X
INNER JOIN Y ON X.d = Y.e
WHERE
X.a in (1, 2, 3)
AND X.b IS NULL
AND X.c in (4, 5 ,6)
AND X.d in (7, 8, 9)
改变后INNER JOIN
的LEFT JOIN
,查询是非常快:
SELECT *
FROM X
LEFT JOIN Y ON X.d = Y.e
WHERE
X.a in (1, 2, 3)
AND X.b IS NULL
AND X.c in (4, 5 ,6)
AND X.d in (7, 8, 9)
查看这些查询的解释计划,第一个查询执行a full scan
,第二个查询仅对Index Scan (range)
我的复合索引执行。我看到了其他有关SO的文章,但它们有不同的场景。
为什么计划会有如此差异?
使用不同计划的原因是,LEFT JOIN将强制表的连接顺序与它们在查询中出现的顺序匹配。如果没有左联接,优化器将为您选择联接顺序,在这种情况下,它将首先选择非常小的表。(您可以explain
通过查看表的列出顺序在您的表中查看。)切换连接顺序后,X的索引将更改为KEY d,该键的数据集必须比复合键大得多。
要解决此问题,请将您的选择更改为SELECT STRAIGHT_JOIN *
。相对于此,它是首选方法,USE INDEX
以便优化器仍可以为表X选择最佳键。。。您可能会找到比a,b,c,d更好的复合键,或者如果X中的数据发生了巨大变化,则可以使用其他键之一一点之后可能会更好。
我必须指出,您通常不能只切换到LEFT JOIN。返回的数据通常会有所不同!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句