ben*_*n.d 4 mysql performance inner-join left-join mariadb
我有两张桌子
表 X:数百万条记录
|-----|-----|-----|-----|
| a | b | c | d |
|-----|-----|-----|-----|
Run Code Online (Sandbox Code Playgroud)
表Y:只有几条记录
|-----|-----|
| e | f |
|-----|-----|
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
将 更改INNER JOIN为 a后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)
Run Code Online (Sandbox Code Playgroud)
查看这些查询的解释计划,第一个查询正在执行 a full scan,而第二个查询仅在我的复合索引上执行 a Index Scan (range)。我在 SO 上看到了其他帖子,但他们有不同的场景。
为什么计划有如此大的差异?
不同计划的原因是 LEFT JOIN 将强制表的连接顺序与它们在查询中出现的顺序相匹配。如果没有左连接,优化器将为您选择连接顺序,在这种情况下,它将首先选择非常小的表。(您可以在您的explain通过查看表列出的顺序来看到这一点。)一旦切换连接顺序,X 的索引就会更改为 KEY d,它必须具有比复合键大得多的数据集。
要解决此问题,请将您的选择更改为SELECT STRAIGHT_JOIN *. 这比USE INDEX以便优化器仍然可以为表 X 选择最佳键...您可能会找到比 a、b、c、d 更好的复合键,或者如果 X 中的数据发生巨大变化,则您的其他键之一过了一点可能会更好。
我必须指出,通常不能直接切换到 LEFT JOIN。返回的数据通常会不同!
| 归档时间: |
|
| 查看次数: |
4971 次 |
| 最近记录: |