Mysql 澄清创建临时表的联接顺序

Mysql 澄清创建临时表的联接顺序,mysql,join,optimization,explain,Mysql,Join,Optimization,Explain,我在mysql中有一个大型查询,涉及将多个表连接在一起。它太慢了,所以我已经做了“解释”,看到它正在创建一个临时表,我怀疑它占用了大部分执行时间。我发现了一些相关信息: 描述可能创建临时表的条件。(“服务器在以下情况下创建临时表…”[强调添加]) 这是一个相关的SO问题,它提供了指向文档的链接,并将其应用于特定案例 这是一个相关的问题,讨论了连接的求值顺序 按照我编写联接的顺序,我的查询似乎不符合文档1中列出的任何条件。但是,通过实验,我发现如果删除我的orderby子句,就不会创建临时表。这让

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

  • 描述可能创建临时表的条件。(“服务器在以下情况下创建临时表…”[强调添加])
  • 这是一个相关的SO问题,它提供了指向文档的链接,并将其应用于特定案例
  • 这是一个相关的问题,讨论了连接的求值顺序
  • 按照我编写联接的顺序,我的查询似乎不符合文档1中列出的任何条件。但是,通过实验,我发现如果删除我的
    orderby
    子句,就不会创建临时表。这让我从文件中看到了这条规则:

    对包含ORDER BY子句和其他GROUP BY子句的语句的求值,或对ORDER BY或GROUP BY包含联接队列中第一个表以外的表中的列的语句的求值

    这与上面#2中的示例中所使用的规则相同,但在#2中,OP在子句中显式地具有来自多个表的列,因此这至少在表面上是不同的

    此外,当我查看
    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
    
    我想说,我的
    orderby
    子句根据我编写查询的顺序,只使用“连接队列中的第一个表”中的列。另一方面,
    explain
    的输出表明它首先考虑表B,然后考虑表A

    以下是问题:

  • 上面引用的使用临时表的规则是指我编写表的顺序还是软件选择评估表的顺序
  • 如果是我编写它们的顺序,这是否意味着连接的顺序会影响性能?(似乎与上述第3点的说法相矛盾。)
  • 如果是软件选择评估它们的顺序,有没有办法强迫或欺骗它选择不使用表的顺序
  • 它指的是优化人员评估它们的顺序(加入队列)。优化者甚至可能不知道sql语句中表的顺序

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

  • 结果没有影响

    结果和表现是两码事。事实上,有一个对答案投赞成票的评论说

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

  • 您可以使用以下命令告诉Optimizer首先处理哪个表:

    直线联接与联接类似,只是左表总是在右表之前读取。这可以用于连接优化器将表按错误顺序放置的(少数)情况

  • 然而,你需要小心,因为你束缚了乐观主义者的手。请参阅“讨论直螺纹联接的优缺点”主题

    记录的数量,其中标准、索引-它们都在优化器决定表的处理顺序中发挥作用。没有什么灵丹妙药,你需要玩一玩,也许你可以骗乐观主义者改变桌子的顺序

    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
      的tmp&filesort:
      索引(c3,c4)
      。不,这与索引(c3)、索引(c4)不同

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

    • 直联
      力指数
      通常是个坏主意,只能作为最后手段使用。这可能有助于今天的质疑,但对明天不利

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


    更多提示:

    谢谢,但这与具体的(大大简化的)示例联系太紧密,没有多大帮助。我问的问题比这个更一般。这个一般性主题的问题是有太多的变体。如果你把
    A.c4
    改为
    B.c4
    ,我说的大部分都是“错的”。我的食谱尽我所能地用“一般”语句来描述。@Brick-在重读你的问题时,我能想到十几个“如果查询有……那么……如果……那么……其他……”。没有足够的空间来解释它们。相关子查询,不相关子查询,左,按x顺序按y分组,按a.x顺序按b.y分组,其中a.x=。。b.y=..,SELECT*vs SELECT short list,缺少索引,额外索引等等--所有这些都会导致异常。