代码之家  ›  专栏  ›  技术社区  ›  benjamin.d

Mysql-左连接比内连接快

  •  3
  • benjamin.d  · 技术社区  · 8 年前

    我有两张桌子

    表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 到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)
    

    查看这些查询的解释计划,第一个查询是执行 full scan 当第二个只做 Index Scan (range) 在我的复合索引上。 我看到了其他帖子,但他们有不同的场景。

    为什么计划中会有如此大的差异?

    3 回复  |  直到 8 年前
        1
  •  5
  •   Tim Mickey    8 年前

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

    要解决此问题,请将选择更改为 SELECT STRAIGHT_JOIN * . 这比 USE INDEX 这样优化器仍然可以为表X选择最佳键。。。您可能会找到一个比a、b、c、d更好的复合键,或者如果您在X中的数据发生了显著的变化,那么在一个点之后,您的另一个键可能会更好。

    我必须指出,通常不能切换到左连接。返回的数据通常会有所不同!

        2
  •  0
  •   A.D.    8 年前

    A. LEFT JOIN 不快于 INNER JOIN . 它始终取决于表的结构,而是否对其应用了正确的键索引。如果没有使用依赖项或索引 Left Join 速度要快得多,因为它不会扫描整个表。但是,如果场景发生了变化,并且两个表都依赖于适当的集群索引,那么两个连接都会尽可能地提供数据。

    左连接 如果没有对任何表进行适当的索引,速度总是更快。有时还取决于数据和数据结构,因为每个场景都有自己的足够逻辑。

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

        3
  •  0
  •   Rick James diyism    8 年前

    滴 INDEX(a) 与您的综合索引重复

    代替 INDEX(b) 具有 INDEX(b,d) .

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