MySQL-LEFT JOIN比INNER JOIN快

本杰明

我有两张桌子

表X:百万或记录

|-----|-----|-----|-----|
|  a  |  b  |  c  |  d  |
|-----|-----|-----|-----|

表Y:仅几条记录

|-----|-----|
|  e  |  f  |
|-----|-----|

X.d 允许我加入两个表 X.d = Y.e

我有以下索引:

  • (Xa)
  • (Xb)
  • (Xc)
  • (Xd)
  • (Xa,Xb,Xc,Xd)
  • (是)

我们的应用程序之一正在执行以下查询,该查询需要花一些时间才能运行:

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 JOINLEFT 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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章