关于mysql优化:三高Mysql-Mysql索引和查询优化偏理论部分

13次阅读

共计 11214 个字符,预计需要花费 29 分钟才能阅读完成。

引言

​ 内容为慕课网的 ” 高并发 高性能 高可用 MySQL 实战 ” 视频的学习笔记内容和集体整顿扩大之后的笔记,本节内容讲述的索引优化的内容,另外本局部内容波及很多优化的内容,所以学习的时候倡议打开《高性能 Mysql》第六章进行回顾和理解,对于 Mysql 数据的开发同学来说大抵理解外部工作机制是有必要的。

​ 因为文章内容过长,所以这里拆分为两局部,高低局部的内容均应用sakila-db,也就是 mysql 的官网案例。第一局部讲述优化的实践和 Mysql 过来的优化器设计的缺点,同时会介绍更高的版本中如何修复欠缺这些问题的(然而从集体看来新版本那些优化基本算不上优化,甚至有的优化还是照抄的 Mysql 原作者的实现的,倒退了这么多年才这么一点问题还是要归功于 Oracle 这种极致商业化公司的功绩)。

如果内容比拟难,能够追随《Mysql 是怎么样运行》集体读书笔记专栏补补课,集体也在学习和同步更新中。

地址如下:https://juejin.cn/column/7024…。

【知识点】

  • Mysql 索引内容的介绍
  • 索引的应用策略和应用规定
  • 查问优化排查,简略理解 Mysql 各个组件的职责

前置筹备

sakila-db

​ sakila-db 是什么?国外很火的一个概念,指的是国外的电影租赁市场应用租赁的形式进行电影的观看非常受外国的喜爱。这里介绍是因为后续的内容都用到了这个案例。所以咱们须要提前把相干的环境筹备好,从如下地址进行下载:

​ 下载地址:https://dev.mysql.com/doc/ind…

《高性能 Mysql》的 SQL 案例也是应用官网的 example

work-bench

​ work-bench 是官网开发的数据库关系图的可视化工具,应用官网案例的具体关系图展现成果如下,通过这些图能够看到 Sakila-db 之间的大抵关系:

work-bench 也是开源免费软件,下载地址如下:

https://dev.mysql.com/downloa…

​ 装置 workbench 和下载 sakila-db 的形式这里不做记录,在运行的时候须要留神先建设一个数据库运行 sheme 文件,而后执行 data 的 sql 文件,最终在 navicat 中查看数据:

注释局部

索引类型

​ 首先是索引的特点以及作用:

  1. 索引的目标是为了晋升数据的效率。
  2. 对于 ORM 框架来说索引的应用至关重要,然而 ORM 的优化往往难以顾及所有业务状况,后续被逐步废除。
  3. 不同的索引类型实用于不同的场景。
  4. 索引关键在于缩小数据须要扫描的量,同时防止服务器外部对内容排序和长期表(因为长期表会索引生效),随机 IO 转程序 IO 等特点

​ 上面介绍 Mysql 相干的索引类型:

  • 哈希索引:哈希索引适宜全值匹配和准确查找,查问的速度十分快 在 MySQL 中只有 memory 存储引擎显式反对此索引,memory 还反对非惟一哈希索引的,是哈希索引设计外面比拟非凡的。
  • 空间索引:空间索引是 myisam 表反对,次要用作天文数据存储,这里蕴含一个叫做 GIS 的玩意,然而 GIS 在 Postgre 中应用比 MySQL 要杰出很多,所以 mysql 中空间索引是无关紧要的货色。
  • 全文索引:全文索引也是 myisam 独有反对的一种索引类型。适宜应用的场景为全值匹配的场景和关键字查问,对于大文本的关键字匹配能够无效解决。
  • 聚簇索引:聚簇索引是 innodb 存储引擎的默认存储引擎。
  • 前缀压缩索引:留神这个索引针对的是 myisam 存储引擎,目标是为了让索引放入内存中排序,,前缀压缩的办法是首先保留索引块的第一个值,而后在保留第二个值,存储第二个值相似(长度, 索引值)的模式寄存前缀索引。

其余索引类型注意事项:

​ Archive 在 5.1 之后才反对单列自增索引。

​ MyISAM 反对压缩之后的前缀索引,使得数据结构占用更小。

哈希索引

​ 在 Mysql 中惟一显式实现哈希索引的存储引擎为 Memory,Memory 是存在非惟一哈希索引,同时 BTree 也反对“自适应哈希索引的形式“兼容哈希索引。

上面是哈希索引特点:

  • 键存储的是索引哈希值,留神不是索引值自身,而值存储的是指向行的指针
  • 留神此哈希索引无奈防止行扫描,然而在内存中指针十分快通常能够忽略不计
  • 留神只有哈希值依照程序排序,然而行指针不是依照程序排序
  • 哈希不反对:局部索引笼罩,只反对全索引笼罩,因为应用全副的索引列计算哈希值
  • 哈希索引反对等值匹配操作不反对范畴查问,比方等于,in 子查问,不全等。
  • 如果呈现哈希抵触,哈希索引将进化为链表程序查问,同时保护索引的开销也会变大

聚簇索引

​ 聚簇示意数据行的值紧凑存储在一起。而 innodb 聚簇的值就是主键的值,所以通常应用都是主键上的索引,针对主键索引的抉择非常重要。因为本局部着重索引优化,聚簇索引这里就不再讲述了。

​ MyISam 和 Innodb 的主键索引区别是 MyISam 的索引很简略,因为数据行只蕴含行号,所以索引 间接存储列值和行号,数据独自寄存另一处,相似于一个惟一非空索引,索引和数据不在一处,MyISam 的索引设计比 InnoDB 简略很多,这和 MyIsam 不须要反对事务也有间接关系,而 innodb 将索引和行数据放入一个数据结构,将列进行紧凑的存储。

聚簇索引有上面长处

  • 紧凑存储数据行,所以能够只扫描大量磁盘就能够获取到数据
  • 数据拜访的速度十分快,索引和数据放在同一颗 BTree 中,比非聚簇索引查问快很多
  • 笼罩索引能够间接 缩小回表

当然索引也有上面的毛病:

  • 对于非 IO 密集型利用,聚簇索引的优化无意义。
  • 插入速度依赖于插入程序,然而如果不是自增插入则须要 optimize table 从新组织表。
  • 更新代价十分高,因为 BTree 要保障程序排序须要移动数据页地位和指针。
  • 主键数据插入过满数据页存在页决裂问题,行溢出会导致存储压力加大。
  • 聚簇索引导致全表扫描变慢,页决裂导致数据问题等。
  • 二级索引须要回表查问聚簇索引能力查问数据。
  • 二级索引因为须要存储主键开销会更大,至多在 InnoDb 中保护一个二级索引的开销是挺大的。

压缩索引

​ 压缩索引的特点是应用更少的空间寄存尽可能多的内容,然而这样的解决形式仅仅实用于 IO 密集型的零碎,压缩前缀存储模式最大的缺点是无奈应用二分法进行查找,同时如果应用的倒序索引的形式比方 order by desc 的形式可能会因为压缩索引的问题存在卡顿的状况。

Bree 索引的特点

  • 叶子结点存在逻辑页和索引页两种,通常非最底层叶子结点都是索引页,最底层索引页由链表串联。
  • Btree 索引会依据 建表程序 对于索引值进行排序,索引建表时候倡议将常常查问的字段往前挪。
  • Btree 索引适宜的查问类型:前缀查问,范畴查问,键值查问(哈希索引)

自适应哈希索引

​ 当 innodb 发现某些索引列和值应用频繁的时候,BTree 会在此基础上主动创立哈希索引辅助优化,然而这个行为是不受内部管制的,齐全是外部的优化行为,如果不须要能够思考敞开。

Btree 查问类型

​ 针对 Innodb 的 Btree 索引,有上面几种常见的查问形式:

  • 全值匹配:等值匹配的形式,全值匹配适宜哈希索引进行查问
  • 最左匹配准则:二级索引的查问条件放在 where 最右边
  • 前缀匹配:只应用索引的第一列,并且 like‘xxx%’
  • 范畴匹配:范畴匹配索引列到另一列之间的值
  • 范畴查问和准确匹配联合,一个全值匹配,一个范畴匹配
  • 笼罩索引查问:笼罩索引也是一种查问形式,

索引策略

​ 上面是对于建设索引的一些常见策略:

  1. 第一件事件须要思考的是预测那些数据为热点数据或者热点列,依照《高性能 Mysql》介绍,对于热点列来说有时候要违反最大选择性的准则,通过建设时常搜寻的索引作为最左前缀的默认的设置。同时优化查问须要思考所有的列,如果一个查问的优化会毁坏另一个查问,那么就须要优化索引的构造。
  2. 第二件事件是思考 where 的条件组合,通过组合多种 where 条件,须要思考的是尽可能让查问重用索引而不是大规模的建设新索引。
  3. 防止多个范畴进行扫描,一方面是范畴查问会导致,然而对于多个等值的条件查问,最好的方法是尽量管制搜寻范畴。

​ 对于索引的策略咱们还须要理解上面的细节

  • 单行拜访很慢,特地是随机拜访要比程序拜访要慢更多,一次性加载很多数据页会造成性能的节约。
  • 程序拜访范畴数据很快,程序 IO 的速度不须要多磁道查找,比随机的拜访 IO 块很多,程序拜访也能够应用 group by 进行聚合计算。
  • 索引笼罩速度很快,如果查问字段蕴含了索引列,就不须要回表。

索引碎片优化

​ Innodb 的数据结构和个性会导致索引存在数据碎片,对于任何存储构造来说程序的存储构造是最合适的,并且索引程序拜访要比随机拜访快更多,数据存储的碎片比索引自身简单很多,索引碎片通常蕴含上面的状况:

  • 行碎片:数据行的数据被存储在多个数据页当中,碎片可能会导致性能的降落。
  • 行间碎片:逻辑程序上的页,行在磁盘上不顺序存储,行间数据碎片会导致全表扫描。
  • 残余空间碎片:数据页的间隙有大量的垃圾数据导致的节约。

​ 对于下面几点,对于 myisam 都有可能呈现,然而 innodb 的行碎片不会呈现,外部会挪动碎片重写到一个片段。

​ 索引碎片的解决形式:在 Mysql 中能够通过 optimize table 导入和导出的形式重新整理数据,避免数据碎片问题。

索引规定

  • 索引必须依照索引程序从左到右匹配
  • 如果在查问两头呈现范畴,则范畴查问之后的索引生效
  • 不能跳过索引列的形式查问(和 B +tree 索引数据结构设计有关系)

​ 接着是索引程序问题,因为 BTree 的构造个性,索引都是依照建设程序进行查找的,通常不蕴含排序和分组的状况下,把选择性最高的索引放在最左列是一个广泛正确策略。

​ 如何查看索引基数:show index from sakila.actor,还有一种形式是通过information_schema.statistics 表查问这些信息,能够编写为一个查问给出选择性较低的索引。

​ 当 innodb 关上某些表的时候会触发索引信息的统计,比方关上 information_schema 表或者应用 show table statusshow index的时候,所以如果在零碎要运行压力较大的业务期间尽量避开这些操作。

冗余反复索引

​ Mysql 容许同一个列上创立多种类型的索引,有时候会因为建表的个性问题给字段反复建索引造成不必要的性能节约。冗余索引和反复索引有什么区别?

​ 冗余索引:是合乎最左匹配法令的状况下反复对雷同列建设索引。

​ 反复索引:是对于不最做的形式创立的索引就有可能是反复创立索引。

​ 比方联结索引:(A,B) 如果在创立(A)或者(A,B)都是反复索引,然而创立(B)就不是反复索引而是冗余索引。另外某些非常非凡的状况下可能用到冗余索引,然而这会极大的减少索引保护的开销,最为直观的感触是插入、更新、删除的开销变得很大。

多列索引

​ 首先多列索引不是意味着 where 字段呈现的中央就须要退出,其次多列索引尽管在当初支流应用版本中(5.1 版本之后)实现了索引外部合并,也就是应用 and or 或者 andor合并的形式相交应用索引,然而他存在上面几个毛病

  • 外部优化器的合并和计算非常消耗 CPU 的性能,索引反而减少数据查问复杂度,效率也不好
  • 往往会存在优化适度的状况,导致运行成果还不如全表扫描
  • 呈现多列索引合并通常意味着建设索引的形式不对,存在反向优化的嫌疑

文件排序

​ 文件排序遵循 Innodb 的 Btree 索引的最根本准则:最左前缀准则 ,如果索引列的程序和 order by 排序统一,并且查问列都和排序列都一样才会用索引代替排序,对于多表查问则排序字段 全为第一个表 能力进行索引排序。然而有一个特例那就是排序字段的前导列为 常量 的时候仍然能够应用索引排序。

​ 案例:rental 表的联结索引列进行排序

Backward index scan 是 MySQL-8.0.x 针对下面场景的一个专用优化项,它能够从索引的前面往前面读,性能上比加索引提醒要好的多

EXPLAIN select rental_id,staff_id from rental where rental_date = '2005-05-25' order by inventory_id desc, customer_id asc;
-- 1 SIMPLE rental ref rental_date rental_date 5 const 1 100.00 Using filesort

EXPLAIN select rental_id,staff_id from rental where rental_date = '2005-05-25' order by inventory_id desc;
-- Backward-index-scan
-- Backward index scan 是 MySQL-8.0.x 针对下面场景的一个专用优化项,它能够从索引的前面往前面读,性能上比加索引提醒要好的多
-- 1 SIMPLE rental ref rental_date rental_date 5 const 1 100.00 Backward index scan

EXPLAIN select rental_id,staff_id from rental where rental_date = '2005-05-25' order by inventory_id, staff_id;
-- 1 SIMPLE rental ref rental_date rental_date 5 const 1 100.00 Using filesort
-- 无奈应用索引
EXPLAIN select rental_id,staff_id from rental where rental_date > '2005-05-25' order by inventory_id, customer_id;
-- 1 SIMPLE rental ALL rental_date 16008 50.00 Using where; Using filesort

EXPLAIN select rental_id,staff_id from rental where rental_date = '2005-05-25' and inventory_id in (1,2) order by customer_id;
-- 1 SIMPLE rental range rental_date,idx_fk_inventory_id rental_date 8 2 100.00 Using index condition; Using filesort

explain select actor_id, title from film_actor inner join film using(film_id) order by actor_id;
-- 1 SIMPLE film index PRIMARY idx_title 514 1000 100.00 Using index; Using temporary; Using filesort
-- 1 SIMPLE film_actor ref idx_fk_film_id idx_fk_film_id 2 sakila.film.film_id 5 100.00 Using index

查问优化排查

​ 查问优化的排查意味着咱们须要先理解 Mysql 的各个组件在各步骤中做了哪些事件,上面这张图来自于《高性能 Mysql》,对于一次客户端的申请,大抵分为上面的流程:

  1. 客户端发送申请
  2. 服务器查问执行缓存

    • 不重要,8.0 之后曾经删除
  3. 服务端进行 SQL 解析和预处理

    • 权限查看
    • 词法解析
    • 语法树
  4. 优化器生成执行打算

    • 优化器存在的问题?
    • 优化器如何工作?
  5. 依据执行打算调用存储引擎的 APi 接口执行查问
  6. 后果返回客户端

​ 对于关系型的数据库来说,外围局部在于查问优化器和执行打算的局部,因为不论咱们如何编写 SQL 语句,如果没有弱小的优化器和执行打算那么一切都是空谈,所以本局部的重点也会围绕优化器进行解说,在此之前咱们先看看其余组件的工作:

​ 首先查问缓存不须要过多解释,他的作用是当用户反复执行一个查问的时候会外部对于后果进行缓存,然而一旦用户批改查问条件,缓存就生效了,在晚期的互联网环境中这种解决很不错,能够缩小磁盘 IO 和 CPU 的压力,然而到了当初的环境下显然不适宜,所以 8.0 删除也是能够了解的。

​ 接着是解析器,解析器这部分次要工作是通过解析语法造成解析树对于语句进行预处理,预处理能够类看作咱们编译器把咱们写的编程语句“翻译”为机器代码的过程,让下一步的优化器能够意识这颗解析树去进行解析,

​ 如果想要理解 SQL 解析优化的底层过程,能够从这篇文章动手:

​ SQL 解析在美团的利用 – 美团技术团队 (meituan.com)

​ 在下面的博客中提到了一个 DBA 必须把握的工具pt-query-digest,剖析慢查问日志,上面这个文章中提供了一个理论的案例来排查和优化,案例较为简单适宜刚接触这个工具的人进行学习和思考,这里一并列进去了。

​ 应用 pt-query-digest 剖析 RDS MySQL 慢查问日志 | 亚马逊 AWS 官网博客 (amazon.com)

SQL 解析局部笔记:

词法剖析:外围代码在 sql/sql_lex.c 文件中的,MySQLLex→lex_one_Token

MySQL 语法分析树生成过程 :全副的源码在sql/sql_yacc.yy 中,在 MySQL5.6 中有 17K 行左右代码

最外围的构造是 SELECT_LEX,其定义在 sql/sql_lex.h

​ 上面咱们来深刻看看优化器的局部工作内容以及 Mysql 优化历史:

​ 因为讲述优化器的内容较少,这里间接总结《高性能 Mysql》的内容,优化器也不须要钻研和记忆,因为随着版本的迭代不断更新优化器会一直调整,所有要以实在试验为准:

1. 子查问关联

​ 上面的查问在通常状况下咱们会认为先进行子查问,而后通过 for 循环扫描 film 表进行匹配操作,而后从 explain 的后果中能够看到这里的查问线进行了全表扫描,而后通过关联索引进行第二层的 for 循环查问,这样的写法相似exists

explain select * from sakila.film where film_id in (select film_id from film_actor where actor_id)
-- 1    SIMPLE    film        ALL    PRIMARY                1000    100.00    
-- 1    SIMPLE    film_actor        ref    idx_fk_film_id    idx_fk_film_id    2    sakila.film.film_id    5    90.00    Using where; Using index; FirstMatch(film)

​ 优化这个子查问的形式应用关联查问代替子查问,然而须要留神这里存在 where 条件才会走索引,否则和下面的后果没有区别:

explain select film.* from sakila.film film  join film_actor actor using (film_id) where actor.actor_id = 1

​ 另一种是应用 exists 的形式进行关联匹配。

explain select * from film where exists (select * from film_actor actor where actor.film_id =  film.film_id and actor.actor_id = 1);

​ 能够看到哪怕到了 5.8 的版本,Mysql 的子查问优化既然没有特地大的改良,所以通常状况下如果不确定 in 查问的内容大小,倡议用 exists 或者 join 进行查问,另外也不要置信什么 in 查问就肯定慢点说法,在不同的 mysql 优化器版本中可能会有不同的成果。

2. union 查问

​ 尽管少数状况下咱们会用 union 替换 or,然而更多的状况是应该尽量避免应用 union,因为 union 查问会产生长期表和两头后果集容易导致优化索引生效,须要留神的是 union会触发外部的排序动作,也就是说 union 会等价于 order by 的排序,如果数据不是强烈要求不能反复,那么更倡议应用 union all,对于优化器来说这样工作更加简略,间接把两个后果集凑在一起就行,也不会进行排序。

​ union 查问能不必就不必,除非是用来代替 or 查问的时候酌情思考是否有必要应用。

​ 最初留神 union 的产生排序不受管制的,可能会呈现意料之外的后果。

3. 并行查问优化

​ 并行查问优化在 8.0 中终于有了实现,能够依据参数:innodb_parallel_read_threads = 并行数 来验证。

​ 因为集体是 M1 的 CPU,读者能够依据本人的理论状况进行试验。

set local innodb_parallel_read_threads = 1;
select count(*) from payment;
set local innodb_parallel_read_threads = 6;
select count(*) from payment;

从执行后果能够看到仅仅是 1 万多条数据的 count(*)查问就有显著直观的差距:

4. 哈希关联

​ 官网文档的介绍地址:Mysql 官网文档哈希关联

​ 在 MySQL 8.0.18 中 Mysql 终于减少了哈希关联的性能。在此之前的版本中,Mysql 的优化器通常只反对 for 循环嵌套关联,曲线救国的办法是建设一个哈希索引或者应用 Memory 存储引擎,而新版本提供的哈希关联则提供了一种新的对关联形式,哈希关联的形式如下:

​ 把一张小表数据存储到 内存 中的哈希表里,通过匹配大表中的数据计算 哈希值,并把符合条件的数据从内存中返回客户端。

​ 对于 Mysql 的哈希关联,咱们间接应用官网的例子:

CREATE TABLE t1 (c1 INT, c2 INT);
CREATE TABLE t2 (c1 INT, c2 INT);
CREATE TABLE t3 (c1 INT, c2 INT);

EXPLAIN
     SELECT * FROM t1
         JOIN t2 ON t1.c1=t2.c1;
-- Using where; Using join buffer (hash join)

​ 除开等值查问以外,Mysql 的 8.0.20 之后提供了更多的反对,比方在 MySQL 8.0.20 及更高版本中,连贯不再须要蕴含至多一个等连贯条件能力应用哈希连贯,除此之外它还包含上面的内容:

-- 8.0.20 反对范畴查问哈希关联
EXPLAIN  SELECT * FROM t1 JOIN t2 ON t1.c1 < t2.c1;
-- 8.0.20 反对 in 关联
EXPLAIN  SELECT * FROM t1 
        WHERE t1.c1 IN (SELECT t2.c2 FROM t2);
-- 8.0.20 反对 not exists 关联
EXPLAIN  SELECT * FROM t2 
         WHERE NOT EXISTS (SELECT * FROM t1 WHERE t1.c1 = t2.c2);
-- 8.0.20 反对 左右内部连贯
EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1;
EXPLAIN SELECT * FROM t1 RIGHT JOIN t2 ON t1.c1 = t2.c1;

留神 8.0.18 版本的哈希关联 仅仅反对 join 查问,对于可能会带来笛卡尔积的左连和右连贯查问是不反对的。然而在后续的版本中提供了更多查问条件反对

另外,8.0.20 版本之前想要查看是否应用 hash join,须要联合 format=tree 选项。

​ 最终 Mysql 在 8.0.18 版本中已经提供过开关哈希索引和设置优化器提醒 optimizer_switch 等参数来断定是否给予 hash join 的提醒,真是闲的蛋疼(官网本人也这么认为)所以在 8.0.19 立马就把这些参数给废除。

​ 留神哈希连贯不是没有限度的,理解哈希关联的流程就会发现如果哈希表过大,会导致整个哈希关联过程在磁盘中实现其速度可想而知,所以官网提供了上面的倡议:

  • 减少join_buffer_size,也就是减少哈希关联的哈希表缓存大小,避免进入磁盘关联。
  • 减少 open_files_limit 数量,这个参数什么意思这里就不介绍了,意义是减少这个参数能够减少关联的时候关联次数。

吐槽:说句心里话自 Mysql 被 Oracle 收买之后,越来越商业化的同时提高也越来越小,in 查问优化这一点其实在很多开源库甚至 Mysql 的原作者给解决了,然而 Mysql 到了 8.0 仍然和多年前的《高性能 Mysql》后果没有差异。哎。。。。。

Mysql 数据库的倒退也通知咱们时刻放弃凋谢的心态,吸取教训正视有余和改良,才不会被时代逐步淘汰。

5. 涣散索引

​ 涣散索引在 Mysql5.6 之后曾经反对,涣散索引简略了解就是在进行多列索引扫描的时候,即便次索引不是有序的,然而跳过索引是有序的,也能够走索引来疾速匹配数据。

 涣散索引的优化细节放到了下半局部的文章,这里简略讲述一下大抵的工作原理。

  1. 查问同时更新数据

​ 在 Postgresql 中,反对上面的语法:

update tbl_info
set name = tmp.name
from 
(select name from tbl_user where name ='xxx')
tmp
[where ....]

-- 比方上面的写法:UPDATE `sakila`.`actor` SET `first_name` = 'PENELOPE'
from 
(select address,address_id from address where address_id = 1) tmp
 WHERE `actor_id` = 1 and actor.actor_id = tmp.address_id;

​ 然而很惋惜这种语法在 Mysql 是没有方法实现也是不反对的,哪怕到了 8.0.26 仍然没有反对,这和 Mysql 的优化器设计有着实质的关系。

  1. 优化器提醒设置

优化器提醒没有多少意义,这里间接略过了。

  1. 最大值和最小值优化

​ 从理论的状况来看 Mysql 最大值和最小值这两个函数应用并不是很多所以不再进行介绍了,另外无论什么样的数据库都不是很倡议频繁应用函数,而是改用业务 + 简略 SQL 实现高效索引优化。

其余慢查问优化

​ 对于慢查问的优化咱们须要分明优化是分为几种类别的,在 Mysql 中优化策略分为 动静优化 动态优化:动态优化次要为优化更好的写法,比方常数的排序和一些固定的优化策略等,这些动作通常在一次优化过程中就能够实现。而动静优化策略要简单很多,可能会在执行的过程中优化,有可能在执行过后从新评估执行打算。

​ 动态优化是受优化器影响的,不同版本有不同状况,所以这里讲述动静优化的状况,而动静优化次要蕴含上面的内容:

  • 关联表程序,有时候关联表程序和查问程序不肯定雷同。
  • 重写外连贯为内连贯:如果一个外连贯关联是没有必要的就优化掉外连贯关联。
  • 等价替换,比方 a>5 and a= 5 被优化为 a >= 5,相似数学的逻辑公式简化
  • 优化 count()、max()、min()等函数:有时候找最大和最小值只须要找最大和最小的索引记录,这时候因为不须要遍历,能够认为间接为哈希的获取记录的形式,所以在查问剖析的 extra 外面进行体现(Select tables optimized away),比方:explain select max(actor_id) from actor;
  • 预估和转化常数:以连贯查问为例,如果在查问条件中能够实现预估关联的记录条数,那么对于一个关联查问来说就有可能被优化器作为常数进行优化,因为当时取出记录的条数被优化器通晓。所以优化起来非常简略。
  • 子查问优化:子查问尽管有可能被索引优化然而须要尽量避免应用。
  • 笼罩索引扫描:让索引和查问列统一,是十分高效的优化和执行形式
  • 提前终止查问:提前终止查问指的是当遇到一些查问条件会让查问提前完成,优化器会提前判断放慢数据的匹配和搜寻速度
  • 等值传递,如果范畴查问能够依据关联表查问优化,那么无需 显式的提醒则能够间接搜寻数据。

参考资料:

这里汇总了文章中呈现的一些参考资料:

  • Mysql 官网文档哈希关联
  • SQL 解析在美团的利用 – 美团技术团队 (meituan.com)
  • 应用 pt-query-digest 剖析 RDS MySQL 慢查问日志 | 亚马逊 AWS 官网博客 (amazon.com)

写在最初

​ 上半局部以实践为主,下半局部将会着重实战内容进行介绍。

正文完
 0