MySQL8.0 优化器介绍(一)
- GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
- GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
- 作者: 奥特曼爱小怪兽
- 文章来源:GreatSQL社区原创
前言
线上,遇到一些sql性能问题,需要手术刀级别的调优。optimizer_trace是一个极好的工具,已经有很多资料介绍optimizer_trace怎么使用与阅读。有必要再介绍一下我们平时不太能注意到,但是又对sql性能起着绝对作用的优化器。
优化器是啥?在sql整个生命周期里处于什么样的位置,起到什么样的作用,cmu15445 课程(https://15445.courses.cs.cmu.edu/fall2022/notes/14-optimization.pdf)中对此有一些直观的描述。
以上图片有6大模块,每一个模块都是一个单独的领域。以优化器为例,从1979年到现在,已经发展出来9个细分的研究领域:
- Planner framework
- Transformation
- Join Order Optimization
- Functional Dependency and Physical Properties
- Cost Model
- Statistics
- Query feedback loop
- MPP optimization
- BENCHMARK
接下来会选几个领域做一些更底层的介绍,基于篇幅的限制,某些知识点,点到为止,可以作为以后工作再深入的一个入口。
要让优化器能够得到足够好的plan,有几个必要条件:
- 数据库中的表设置了合适的数据类型。
- 数据库中设置了合适的索引。并且索引上有正确的统计信息。
- 合理的数据分布。
查询优化器的作用:
当我们将查询提交给MySQL执行时,大多数的查询都不像 select * from single_table;那样简单,从单个表读取所有数据就行了,不需要用到高级的检索方式来返回数据。大多数查询都比较复杂,有些更复杂并且完全按照编写的方式执行查询绝不是获得结果的最有效方式。我们可以有很多的可能性来优化查询:添加索引、联接顺序、用于执行联接的算法、各种联接优化以及更多。这就是优化器发挥作用的地方。
优化器的主要工作是准备查询以执行和确定最佳查询计划。第一阶段涉及对查询进行转换,目的是重写的查询可以以比原始查询更低的成本执行查询。第二阶段包括计算查询可以执行的各种方式的成本,确定并执行成本最低的计划。
这里有一个注意的点:优化器所做的工作并不精确科学,因为数据及其分布的变化,优化器所做的工作并不精确。转换优化器的选择和计算的成本都是基于某种程度的估计。通常这些估计值足以得到一个好的查询计划,但偶尔你需要提供提示(hint)。如何配置优化器是另外一个话题。
查询改写(Transformations)
优化器有几种更改查询的改写,在仍然返回相同结果的同时,让查询变为更适合MySQL。
当然,优化的前提是返回的结果符合期望,同时响应时间变短:减少了IO或者cpu时间。改写的前提是原始查询与重写查询逻辑一致,返回相同的查询结果是至关重要的。为什么不同的写法,可以返回相同的结果,又是一门学问:关系数据库基于数学集理论的研究。
举个查询改写简单的例子:
SELECT *
FROM world.country
INNER JOIN world.city
ON city.CountryCode = country.Code
WHERE city.CountryCode = 'AUS'