日常的应用开发中可能需要优化SQL,提高数据访问和应用响应的效率,不同的SQL,优化的具体方案可能会有所不同,但是路径上,还是存在一些共性的。碰巧看到杨老师的这篇文章《第45期:一条 SQL 语句优化的基本思路》,为我们优化一些MySQL数据库的SQL语句提供了可借鉴的路径,值得参考和应用。
SQL语句优化是一个既熟悉又陌生的话题。面对千奇百怪的SQL语句,虽然数据库本身对SQL语句的优化一直在持续改进,但是我们不能完全依赖数据库,应该在给到数据库之前就替它做好各种准备工作,这样才能让数据库来有精力做它自己擅长的事情。
以MySQL为例,一条SQL语句从客户端发出到数据库端返回结果一般会经历几个阶段:词法解析、语法解析、语义解析、逻辑优化、物理优化、最终执行并返回结果。那么这几个阶段,我们DBA能参与的也就是两个阶段:逻辑优化以及少许物理优化。所以在我们DBA这侧,对SQL语句的优化简单来讲就是让我们自己写的SQL语句能更好的适应数据库内置的优化规则,进一步让SQL语句在每个处理阶段能扫描更少的记录数量、字段数量来改善查询效果。
逻辑优化可以理解为基于N多数据库内置规则的预处理,规则定义越全面,对SQL语句优化的就越极致。比如使用表关联代替子查询、分组聚合条件上推、在特定条件下用内连接来替换外连接、视图上推到基表等等一系列优化措施。
物理优化可以理解为数据库按照当前SQL语句涉及到的表统计信息、列统计信息、索引个数、索引优劣、当前运行负载、当前硬件资源等可变因素来决定如何生成最优执行路径的方法。
(1)都没有索引,有的连主键都没有。
(2)都有主键或者唯一索引,但是没有二级索引。
(3)有主键或者唯一索引,也有一些二级索引,并且二级索引可选择性也比较优化。
(4)有主键或者唯一索引,也有一些二级索引,但是这些二级索引可选择性很差。
五、进一步分析优化后SQL语句的执行计划(如果有条件模拟生产环境压力模型),一般考虑如下几点:
(1)这条语句的索引在不同过滤条件下,运行效果忽好忽坏。
例如日期字段,过滤条件为昨天的查询记录数为100条,过滤条件为前天的查询记录数则变为1W条。
(2)这条语句走的索引较优,但是表记录数实在太大,走索引过滤的记录数也很多,需要从表结构这层做些优化。例如改造分区表、拆分表等方法,或者是从业务层面限制这条语句来扫描更少的记录数等。
经过以上几个步骤,一般的语句基本上都能达到比较优化的结果。
虽然上面说的是MySQL数据库,但是一些理论上,其他的关系型数据库都是可以借鉴的。
当然,过程说得很简单,但是实操层面上,可能每个步骤中,都会碰到一些更具体的问题,而每个问题都可能引申出更多的知识点,这就要积累了,才可以更加丰富我们的知识网。