小谈mysql存储引擎优化

小谈mysql存储引擎优化

平时我们在写某个sql时,总会用Explain来查看一下执行计划,看看自己的sql是否和预期一样。执行计划分析也是我们常需要准备技能之一。无论哪种DBMS,决定查询执行计划的优化器是最复杂的部分。把握InnoDB引擎耗费很多时间处理查询的原因,对查询调优相当有用。

一、查询执行过程

mysq服务器中,查询的执行过程大致分为如下3个阶段:

(1). 从用户接受SQL语句,切分语句并分析词法语法,最后生成mysql服务器可以理解的解析器。
(2).确认SQL的解析信息,选择从哪个数据表读取,以及使用哪种索引读取数据表
(3). 借助第二阶段确认的读表顺序或者所选索引,从存储引擎读取数据。

第二阶段会依据第一阶段形成的SQL解析树处理如下内容。

  • 删除不必要的条件,将复合运算简单化
  • 若存在夺标连接,则确定读表顺序。
  • 根据用于各数据表的条件和索引统计信息,确定要使用的索引。
  • 将获取的记录放入临时表,确定是否需要再次加工

查询解析与优化器图如下:
这里写图片描述

下面我们粗略介绍一下优化器、排序缓冲等

二、优化器种类

从作用而言,优化器相当于数据库服务器的大脑,大致分为:

1.” 基于规则的优化“默认不考虑目标数据表的记录数、选择度等,而根据优化器中内置的若干规则制定相应的执行计划。该方式中,制定执行计划不会调查统计信息。所以对相同的查询,其执行方式总是相同的
2.“基于代价的优化”查询时会创建多种可用方法,然后根据各种处理的消耗信息与目标表的统计信息,计算各种执行计划代价,然后从中选择代价最小的执行计划作为最终执行计划。

目前大部分RDBMS几乎都采用代价的优化器

三、优化器何时选择何种扫描方式

3.1 全表扫描

innodb优化器主要在下列情况选用全表扫描:
  • 数据表中的记录较少,使用全表扫描比通过索引读取更快时(一般一个数据表由一个页面组成)
  • Where或On语句中不具备使用索引的合适调价
  • 即使查询可以使用索引范围扫描,优化器判断符合条件的记录太多时(以通过对索引的B-Tree采样而获取的统计信息为准)

大部分DBMS执行全表扫描时,1次可以读取多个数据块或者页面,且可以对读取多少进行调整控制。

在MyISAM中,执行全表扫描时,会从磁盘逐页读取。而在InnoDB或Xtra存储引擎中,连续读取特定数据表的数据页面时,后台线程会自动开始预读作业。预读是指先对将来要用到的数据区域进行预测,然后在对该区域数据的请求到来之前,先将输数据从磁盘督导缓冲池。也就是说执行全表扫描时,最初几个数据页面由前台线程(客户线程)读取,然后从某个时间点开始,读取作业被交由后台线程执行。后台线程从接手读取作业开始,每次读取4-8个页面,并且数量不断增加,一次最大可以读取64个数据页,然后将其存入缓冲池。由于前台线程可以获取并且使用预先存储在缓冲池中的数据,所以查询的处理速度相当快。

3.2 ORDER BY 处理(Using filesort)

处理排序有两种方法,一种是使用索引,另一种是执行查询时,使用filesort处理
像使用索引排序一样,对记录排序时,并非总要进行Filesort排序处理。但在下面情形下,几乎不可能使用索引进行排序。

  1. 排序基准太多,无法依据每个基准全部创建索引。
  2. 要对GROUP BY的结果或者DISTINCT等处理结果排序时
  3. 要对临时表的结果(UNION的结果)重新排序时
  4. 要随机获取结果记录时

3.2 排序缓冲

执行排序操作时,InnoDB会另外分配空间进行排序处理,该空间成为“排序缓冲”(sort buffer).只有排序需要时,才开辟缓冲空间,其大小随着要排序的记录大小而变化。查询执行完毕后,用于排序的空间会立即返还给系统。如果要排序的记录非常少,只用分配的排序缓冲就能完成排序,那么排序的处理速度非常快。但如果排序的记录大于分配的空间时,会发生什么呢。此时会将将要排序的记录划分为很多片段,并将其临时保存到磁盘中。排序时,先在内存中的排序换从中对记录进行排序,然后将排序结果临时存储到磁盘中。之后再获取下一批记录,排序后临时保存到磁盘中,如此反复。最后再根据缓冲哦大小合并并排好序的记录,完成排序处理.

3.3 排序算法:

3种排序处理方式

排序处理方法 执行计划的Extra列
使用索引排序 无内容显示
只对驱动表排序(含无连接情形) 显示Using filesort
将连接结果保存到临时表后,在临时表中排序 显示Using temporary;Using filesort

在执行order by排序时,优化器会检查是否可用索引进行排序处理。若可用索引,则不需FileSort过程,依照顺序读取索引返回结果即可。但若是索引不可用,则检索Where条件的记录,将其存储到排序缓冲中,并进行排序处理。此时

1.对驱动表排序,然后进行连接
2.完成连接后,获取所有符合条件的记录,然后排序

平时所用的sql中大多含有Order by 与limit,处理ORDER BY 或者GROUP BY时,不能只从满足WHERE条件的记录中获取LIMIT 制定的条数。首先要获取所有满足条件的记录,进行排序或者分组后,才能进行limit记录条数限制处理。

2种查询处理方法:

1) 流处理方式:在流处理方式下,无论服务端有多少数据处理,每检索到一条满足条件的记录就立即返回给客户端。
2) 缓冲处理方式:处理带有ORDER BY 或者GROUP BY子句时,由于先要获取符合WHERE条件的所有记录,再排序分组,然后依次发送处理结果,所以无法对查询的结果进行流处理。这种方式称为缓冲(Buffering)处理,与流方式处理。

在ORDER BY的3种排序方式中,只有“使用索引排序方式”采用流处理,其他处理方式均需要先缓冲再进行排序处理。

四、后记

mysql存储引擎还有很多优化机制,仍有待后续深入学习研究。

猜你喜欢

转载自blog.csdn.net/vipshop_fin_dev/article/details/81059053