我想要优化一个查询。为了进行一些测试,我拍摄了生产数据库的快照并创建了该数据库的新测试实例。使用explain
子句,我可以看到两个数据库之间的连接顺序不同。这两个数据库具有相同的版本(MySQL 5.6.19a),相同的引擎(InnoDB),相同的模式,相同的索引,相同的数据,并在相同的材料上执行。唯一的区别是,生产数据库使用更多内存(显然),因为它有更多的连接。
什么可能导致加入顺序不同? 内存使用情况? 索引仍然在测试实例中构建? 生产数据库的索引是碎片化的吗?
答案 0 :(得分:1)
这种情况很少见但很可行。 InnoDB有"统计数据"关于每张桌子上的每个索引;它使用它们来决定执行查询的最佳方式,包括查看表的顺序。
过去的统计数据来自8' random'深入了解BTree,了解行数和数据分布情况。潜水的时间,数字'以及随机性都受到了批评,并且逐渐得到了改善。 5.6.19中只存在一些改进。
另外"成本"决定如何执行查询的模型最近进行了大修(5.7 / 8.0)。 8.0和MariaDB 10.0有"直方图",这将导致更好的查询计划选择。尚未实现(从8.0.0开始):注意哪些块已经缓存;这可能会导致更糟糕的情况。索引因为更多的内容被缓存,因此更快。
由于优化问题的复杂性和大量可能性,甚至有些情况下新版本会选择更糟糕的查询计划。
即使您在相同的计算机上运行相同的查询,查询计划也可能不同。
我认为你已经知道在查询中更改常量可以改变查询计划 - 并且做得更好。我已经看到相同的查询提出了6个不同的查询计划,可能是由于不同的常量。如果您对慢速日志中的查询执行EXPLAIN
,这可能会很烦人 - 您无法确定该查询计划是否在"缓慢"时使用。
我们必须忍受这一切。
您可以执行ANALYZE TABLE
重新计算统计信息。但这可能会使事情变得更糟或更好,这取决于月亮的阶段。它甚至可能(巧合地)让你的两个实例执行相同的查询。
真正的问题是"一台服务器运行查询的速度明显快于另一台服务器吗?" (在考虑缓存,其他活动等之后)。
当JOIN
中的两个表都被过滤时(WHERE
中的某个表),优化程序很难决定。如果还有ORDER BY
和LIMIT
,则更难以决定。
如果您想提供SELECT
,EXPLAIN
和SHOW CREATE TABLE
,我们可以讨论详细信息。 (但是开始一个新问题。)