【问题标题】:Clarification of join order for creation of temporary tables澄清创建临时表的连接顺序
【发布时间】:2017-06-03 08:15:03
【问题描述】:

我在 mysql 中有一个大型查询,涉及将多个表连接在一起。它太慢了,所以我做了“解释”,发现它正在创建一个临时表,我怀疑它占用了大部分执行时间。我找到了一些相关信息:

  1. The mysql docs 描述创建临时表时的条件可能。 (“服务器在这样的条件下创建临时表...”[强调])
  2. 这个相关的 SO 问题 Using index, using temporary, using filesort - how to fix this?,它提供了该文档的链接并将其应用于特定案例。
  3. 这个相关的 SO 问题 Order of join conditions important? 讨论了连接的评估顺序。

我的查询似乎不满足文档 #1 中列出的任何条件,按照我编写连接的顺序。 但是,通过实验,我发现如果我删除我的order by 子句,没有创建临时表。这让我从文档中看到了这条规则:

评估包含 ORDER BY 子句和不同 GROUP BY 子句的语句,或者 ORDER BY 或 GROUP BY 包含来自连接队列中第一个表以外的表的列。

这与上面 #2 的示例中使用的规则相同,但在 #2 中,OP 在 order by 子句中明确包含来自多个表的列,因此至少在表面上有所不同。

此外,当我查看explain 的输出时,我首先列出的表似乎没有被优化器首先使用。放下一个伪查询例如:

select * from A 
join B on A.c1=B.c1
join C on A.c2=C.c2
where A.c3='value'
order by A.c4

我会说我的order by 子句确实只使用“连接队列中的第一个表”中的列根据我编写查询的顺序。另一方面, explain 的输出表明它首先考虑表 B,然后是表 A。

以下是问题:

  1. 上面引用的临时表使用规则是指我编写表的顺序还是软件选择评估它们的顺序?
  2. 如果是我编写它们的顺序,这是否意味着连接的顺序会影响性能? (似乎与上述#3 的主张相矛盾。)
  3. 如果是软件选择评估它们的顺序,有没有办法强制或欺骗它选择不使用表格的顺序?

【问题讨论】:

    标签: mysql join optimization explain


    【解决方案1】:
    1. 它指的是优化器评估它们的顺序(加入队列)。优化器甚至可能不知道您的 sql 语句中表的顺序。

    2. 不,它与 #3 中的内容并不矛盾,因为 answer 明确写道(重点是我的):

    结果

    没有影响

    结果和性能是两个不同的东西。实际上,对答案有一个赞成的评论说

    但它可能会影响查询计划(=> 性能)

    1. 您可以使用straight_join 告诉优化器首先处理哪个表:

      STRAIGHT_JOIN 与 JOIN 类似,只是左表总是先于右表读取。这可用于连接优化器以错误顺序放置表的那些(少数)情况。

    但是,您需要小心这一点,因为您会束缚优化器的手脚。请参阅 this SO 主题,讨论 Straight_join 的优缺点。

    记录数、标准、索引——它们都在优化器决定表的处理顺序中发挥作用。没有灵丹妙药,您需要多试一试,或许您可以欺骗优化器来更改表​​格的顺序。

    【讨论】:

      【解决方案2】:
      select * from A 
      join B on A.c1=B.c1
      join C on A.c2=C.c2
      where A.c3='value'
      order by A.c4
      
      • 优化器将使用各种启发式方法来决定查看表格的顺序。在这种情况下,由于过滤器 (WHERE...),它将以 A 开头。

      • A 上的这个“复合”索引应该消除 ORDER BY:INDEX(c3, c4) 的 tmp&filesort。不,这和INDEX(c3), INDEX(c4)不一样。

      • A 获取行后,BC 可以进入(“嵌套循环连接”)。这些索引很重要:B:(c1)C:(c2)

      • STRAIGHT_JOINFORCE INDEX 通常是个坏主意,只能作为最后的手段使用。它可能有助于今天的查询,但明天会受到伤害。

      • EXPLAIN FORMAT=JSON SELECT ... 提供更多信息,有时甚至指出需要两个 tmp 表。

      更多提示:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

      【讨论】:

      • 谢谢,但这与具体的联系太紧密了 - 大大简化了 - 没有多大帮助。我问的问题比这个更笼统。
      • 这个通用主题的问题在于有太多变种。如果将A.c4 更改为B.c4,我所说的大部分内容都是“错误的”。我的食谱在“一般”陈述中尽我所能。
      • @Brick - 在重读您的问题时,我可以想到十几个“如果查询有......那么......否则如果......那么......其他......”。没有足够的空间来拼写它们。相关子查询、不相关子查询、LEFT、GROUP BY x ORDER BY y、GROUP BY ax ORDER BY、WHERE ax=.. AND by=..、SELECT * vs SELECT 短列表、缺失索引、额外索引等 - - 所有这些都会导致异常。
      猜你喜欢
      • 1970-01-01
      • 2017-12-31
      • 2014-01-30
      • 2010-11-21
      • 1970-01-01
      • 1970-01-01
      • 2014-04-11
      • 2021-10-25
      • 1970-01-01
      相关资源
      最近更新 更多