读书笔记之MySQL查询优化器

关联子查询

由于博主使用的是MySQL5.6版本,这块具体懒得测试(逃
在5.6版本之前不会将子查询的结果集计算出来再与其他表做join,很可能会出现dependent subquery(相关子查询),即外层查询每扫描一条数据,子查询都要重新执行一次,导致性能下降。
在MySQL对子查询处理方式进行了优化,会将子查询的结果临时存储到临时表中,临时表的索引主要使用去除重复记录的,也可以用来在以后需要join的时候使用,称为Subquery Materialize,在explain 的select_type中称为Materialize。

union限制

有时候MySQL无法将限制条件从外层下推到内层,导致原本能限制返回结果的条件无法应用到内层查询的优化上。
如果需要Union的各个子句能够根据Limit只取部分结果集,或者能够先排好序在合并结果集,就需要在union的各个子句分别使用这些子句。如果需要获得正确的顺序,需要加上全局的order by和Limit操作。

索引合并优化

当where子句中包含多个复杂条件的时候,MySQL能够访问单个表的多个索引来合并和交叉过滤的方式来定位需要查找的列。

等值传递

如果存在一个非常大的in()列表,而MySQL优化器发现村咋where、on或者using子句的时候,会将列表的值和另一个表的某个列进行关联,那么的话优化器就会将in()的列表复制到关联的各个表中,由于各个表新增了过滤条件,优化器可以搞笑的从存储引擎过滤数据,但是列表非常大的话,会导致优化和执行变慢

并行执行

MySQL无法利用多核特性来并行执行查询。

哈希关联

MySQL不支持哈希关联,不过可以通过建立哈希索引来实现哈希关联。

松散索引扫描

MySQL不支持松散索引扫描,即无法按照不连续的方式扫描一个索引,MySQL索引扫描需要先定义一个起点和终点,即使需要的数据只是这段索引中的几个,仍然会扫描索引的每一个条目。

最大值和最小值优化

对于MIN()和MAX()查询,如果查询列没有索引的话,MySQL会进行一次全表扫描,如果是主键索引你的话,当MySQL读到第一个满足条件的记录的时候,就是我们要找的最小值,因为主键索引是按照字段的大小顺序进行排列的。

在同一个表上查询和更新

MySQL不允许在同一张表同时进行查询和更新操作,不过我们可以通过临时表的方法来绕过限制,让子查询在update操作打开表之前完成。

优化Count()查询

Count()是一个特殊的函数,可以用来统计某个列值的数量,也可以用来统计行数,不过要求统计列的时候值是非空的(not null),不过要注意一点count()并不是扩展成所有列,而是忽略所有的列而直接统计所有的行数,如果想知道结果集的行数,最好使用count()。
对于MySAIM存储引擎,如果where子句没有任何条件的话,count(*)速度是非常快的,因此不需要实际去计算表的行数,可以利用存储引擎的特性直接获取该值,否则where子句带有参数的话,跟其他存储引擎没有任何区别。

  • 反转where条件来加速特定条件的count()的查询。
  • 使用explain返回的影响行数来代替精确值,可以不需要执行实际的查询语句。
  • 添加汇总表
  • 使用覆盖索引

优化关联查询

  • 确保on 或者using子句的列上有索引
  • 确保任何的group by和order by的表达式只涉及一个表的列。

优化子查询

  • 尽可能使用关联查询

优化group by和DISTINCT

如果可以使用索引来优化的话,就使用索引优化。
无法使用索引的话,group by使用两种策略,使用文件排序或者临时表作分组。如果对关联查询作分组,并且是按照查找表中的某个列进行分组,那么采用查找表的标识列分组的效率会比其他列更高。
如果没有通过order by子句显性指定排序列,当使用group by子句的时候,结果集会自动按照分组的字段进行排序,如果不关心结果集的顺序,而这种默认顺序又导致需要文件排序,可以使用order by null,让MySQL不再进行文件排序。

优化Group by with rollup

对返回的分组结果做超级聚合,可以使用with rollup子句来实现。不过最好将with rollup功能转移到应用程序中处理。

优化limit分页

在需要进行分页操作的时候,可以通过limit加上偏移量实现(可以加上合适的order by子句),不过当偏移量很大的时候,可能会查询很多条记录而只返回少量记录,代价比较大,要进行优化的话,可以是页面中限制分页的数量或者优化大偏移量的性能。
优化分页查询可以使用覆盖索引进行扫描,然后根据需要进行一次关联操作返回所需要的列,它可以让MySQL扫描尽可能少的页面,获取需要访问的记录后在根据关联列返回原表查询需要的所有列。

优化union查询

union通过创建和填充临时表来执行union查询,需要将where,limit,order by子句下推到union的各个子查询找,以便优化器利用这些条件进行优化,除非是需要消除重复的行,否则一定要使用union all,如果没有all关键字的话,MySQL会给临时表添加distinct选项,对整个临时表数据作唯一性检查。

COMMENT AND SHARE

冼毅俊

Xupter√Java√德桌迷√虐心控√mugen爱好者√音乐杂食党√小说发烧友√基本色√鱼迷√stan√bitch√daydreamer


Java研发


长安