【问题标题】:Join order differs for between two instances of the same Mysql DB同一Mysql DB的两个实例之间的连接顺序不同
【发布时间】:2017-05-08 00:00:03
【问题描述】:

有一个我想要优化的查询。为了进行一些测试,我拍摄了生产数据库的快照并为此数据库创建了一个新的测试实例。使用explain 子句,我可以看到两个数据库之间的连接顺序不同。这两个数据库具有相同的版本(MySQL 5.6.19a)、相同的引擎(InnoDB)、相同的模式、相同的索引、相同的数据,并且在相同的材料上执行。唯一的区别是生产数据库使用更多内存(显然),因为它有更多的连接。

什么可能导致连接顺序不同? 内存使用情况? 索引仍在测试实例中构建? 生产数据库的索引是碎片化的?

【问题讨论】:

  • 加入订单是什么意思?
  • 如果您有如下查询:SELECT ... FROM A JOIN B ON B.id = A.id_B JOIN C ON C.id = A.id_C 您可以先在 B 上加入 A,然后在 C 上,或者先在 A 上加入 C,然后在 B 上等... 通常引擎会尝试确定顺序这将限制要读取的行数等...

标签: mysql database join indexing


【解决方案1】:

这很少见,但非常可行。 InnoDB 对每个表的每个索引都有“统计”;它使用它们来决定执行查询的最佳方式,包括查看表的顺序。

以前来自 8 个“随机”的统计数据深入 BTree,以获得对行数和数据分布的粗略感觉。跳水的时机、数字“8”、随机性都被诟病,逐渐得到改善。 5.6.19 中仅存在一些改进。

决定如何执行查询的“成本”模型最近也进行了大修(5.7 / 8.0)。 8.0 和 MariaDB 10.0 具有“直方图”,这应该会导致更好的查询计划选择。尚未实现(从 8.0.0 开始):注意哪些块已被缓存;这可能会选择一个“更差”的索引,因为更多的索引被缓存,因此速度更快。

由于优化问题的复杂性和大量的可能性,甚至在某些情况下,新版本会选择更差的查询计划。

即使您在 same 机器上运行 same 查询,查询计划也可能不同。

我假设您已经知道更改查询中的常量可以更改查询计划——并且做得更好。我已经看到同一个查询提出了 6 个不同的查询计划,大概是由于不同的常量。如果您对在慢日志中找到的查询执行EXPLAIN,这可能会很烦人——您无法确定在“慢”时使用了该查询计划。

我们只需要忍受这一切。

可以使用ANALYZE TABLE 重新计算统计信息。但这可能会使事情变得更糟或更好,具体取决于月相。它甚至可能(巧合地)使您的两个实例执行相同的查询。

真正的问题是“一台服务器运行查询的速度是否明显快于另一台?” (在考虑缓存、其他活动等之后)

JOIN 中的两个表都被过滤时(WHERE 中的某些内容),优化器很难做出决定。如果还有ORDER BYLIMIT,那就更难决定了。

如果您想提供您的SELECTEXPLAINSHOW CREATE TABLE,我们可以讨论详细信息。 (但要开始一个新问题。)

【讨论】:

  • 谢谢,使用ANALYZE TABLE 重新计算统计信息帮助我获得相同的JOIN 订单。对于信息,它使事情变得更糟。但我想处于同样的境地,所以没关系。
猜你喜欢
  • 1970-01-01
  • 2015-08-29
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
  • 1970-01-01
  • 2015-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多