Mysql - LEFT JOIN方式比INNER JOIN快

时间:2018-01-31 11:30:05

标签: mysql performance left-join inner-join mariadb

我有两张桌子

表X:数百万或记录

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

表Y:只有少数记录

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

X.d允许我加入X.d = Y.e

上的两个表格

我有以下索引:

  • (X.a)
  • (X.b)
  • (X.c)
  • (X.d)
  • (X.a,X.b,X.c,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)

查看这些查询的解释计划,当第二个查询仅在我的化合物上执行 full scan 时,第一个查询正在执行 Index Scan (range) 指数。 我在SO上看过其他帖子,但他们有不同的场景。

为什么计划中存在这样的差异?

3 个答案:

答案 0 :(得分:3)

不同计划的原因是LEFT JOIN将强制表的连接顺序与它们在查询中出现的顺序相匹配。如果没有左连接,优化器将为您选择连接顺序,在这种情况下,它将首先选择非常小的表。 (您可以通过查看列表的顺序在explain中看到这一点。)切换连接顺序后,X的索引将更改为KEY d,其必须具有比复合键大得多的数据集

要解决此问题,请将您的选择更改为SELECT STRAIGHT_JOIN *。这比USE INDEX更受欢迎,因此优化器仍然可以为表X选择最佳密钥...您可能会找到比a,b,c,d更好的复合密钥,或者如果X中的数据发生显着变化,一个点后,你的其他一个键可能会更好。

我必须指出,你通常不能只是切换到LEFT JOIN。返回的数据通常会有所不同!

答案 1 :(得分:0)

LEFT JOIN并不比INNER JOIN快。它总是取决于表的结构,而适当的键索引适用于该表。如果您没有使用依赖关系或索引,毫无疑问Left Join会更快,因为这不是扫描完成表。但是如果场景发生变化并且两个表都依赖于正确的集群索引,那么Join都会尽可能提供数据。

  如果您没有对任何表使用正确的索引,

Left Join总是更快。有时它还取决于数据和数据结构,因为每个场景都有自己足够的逻辑。

Post INNER JOIN vs LEFT JOIN例如,这与MsSQL有关,但同时适用于MySql和MsSql。

答案 2 :(得分:0)

删除INDEX(a)作为复合索引的冗余

INDEX(b)替换为INDEX(b,d)

然后提供EXPLAIN SELECT ...,以便我们进一步讨论。