vlambda博客
学习文章列表

数据库表结构设计,sql性能分析与优化

数据库表结构设计,sql性能分析与优化
差一点

我们就擦肩而过了,关注我吧!

原创

实战干货


往期数据库表结构优化设计系列文章:

1、

2、

3、

相信每个开发同事,都应该被DBA或运维同事吐槽过慢sql问题,有的可能DBA直接帮你优化了,但是也有很多公司没有DBA,这个时候就需要我们开发人员自己来排查为什么我的这个sql会这么慢?是否还有优化空间?


一、如何分析寻找慢sql原因


mysql给我们提供了解决办法,查看执行计划,使用EXPLAIN关键字可以模拟优化器执行SQL语句,从而知道MySQL是如何处理你的SQL语句的。帮助我们寻找性能瓶颈。

数据库表结构设计,sql性能分析与优化

以mysql8.0.20版本,执行计划各字段解释如下:


id:代表表的读取顺序,id越大,越先执行,若id相同,执行顺序由上到下;


select_type:数据读取操作的操作类型,主要用于区别普通查询、联合查询、子查询等的复杂查询,select_type类型如下:


1、SIMPLE:简单的查询,查询中不包含子查询或者union;


2、PRIMARY:查询中包含复杂查询,最外层标记为PRIMARY;


3、SUBQUERY:在SELECT或者WHERE列表中包含了子查询;


4、DERIVED:在FROM列表中包含的子查询被标记为DERIVED(衍生),MySQL会递归执行这些子查询,把结果放在临时表里;


5、UNION:若第二个SELECT出现在UNION之后,则被标记为UNION,若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED;


6、UNION RESULT:从UNION表获取结果的SELECT;


table:显示这一行的数据是来源哪张表的;


partitions:查询使用到表分区的分区名;


tye:显示查询使用了何种类型,注意:我们日常业务系统sql要尽可能达到range级别,最好是ref级别;


从最好到最差依次是:system>const>eq_ref>ref>range>index>ALL

1、system:表只有一行记录(等于系统表),这是const类型的特例,平时不会出现,这个也可以忽略不计;


2、const:表示通过索引一次就找到了,const用于主键索引或者唯一索引。因为只匹配一行数据,所以很快。如将主键至于where列表中,MySQL就能将该查询转换为一个常量;


3、eq_ref:唯一性索引,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描;


4、ref:非唯一索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体;


5、range:只检索给定范围的行,使用了索引,然后在你的where语句中出现了between、<、>、in等的查询,这种范围扫描索引扫描比全表扫描要好,因为他只需扫描部分数据,不用扫描全部索引;


6、index:遍历索引树以找到匹配行;


7、all:遍历全表,以找到匹配行,index通常比ALL快,因为索引文件通常比数据文件小;

possible_keys:查询涉及的字段上若存在索引,则该索引将被列出,但索引不一定被查询实际使用


key:实际使用的索引,若没有使用索引,则为null;


key_len:表示索引中使用的字节数,key_len显示的值为索引最大可能长度,并非实际使用长度;


ref:哪些列或常量被用于查找索引列上的值,可能是一个常数;


rows:大致估算找到所需的记录,所需要读取的行数;


Extra:十分重要的额外信息,最好情况就是Using index,Using where;


1、Using filesort:mysql无法使用索引完成排序操作,而变成文件排序;


2、Using temporary:使用了临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序order by 和分组查询 group by;


3、Using index:表示相应的select操作中使用了覆盖索引(Coveing Index),避免访问了表的数据行,效率不错!如果同时出现using where,表明索引被用来执行索引键值的查找;


4、Using where:表示使用了where过滤;


5、Using join buffer:使用了连接缓存;


6、impossible where:where子句查询的值总是空,不能用来获取任何数据;


7、distinct:优化distinct,在找到第一匹配的元组后即停止找同样值的工作;


总结:通过对执行计划结果分析,我们就可以找到慢sql的原因,其中大部分的原因就是索引失效或者是没加索引导致的;



二、索引失效


假设我们建了一个复合索引,索引使用情况,如下图所示

数据库表结构设计,sql性能分析与优化

索引失效情况总结:


1、最左前缀法则:如果是多列的复合索引,我们的sql where条件里的列,从左向右要和索引列顺序保持一致,且不能跳过索引中间的列,但是可以跳过后面的列;


2、在索引列上进行操作包括(函数、计算、自动或手动类型转换),会导致索引失效而转向扫描全表;


3、尽量使用覆盖索引(索引列和查询列一致),减少select *;


4、使用不等于(!=或者<>)的时候无法使用索引,会导致全表扫描;


5、is null,is not null 也无法使用索引;


6、like以 % 通配符开头,mysql索引失效会变成全表扫描操作;


7、or 会使索引失效;


8、使用了大于号>或小于<号的列,后面列索引会失效;


速记口诀如下图:


数据库表结构设计,sql性能分析与优化


三、其他优化查询,in和exists


注:in先执行子查询,后执行外层查询;exists先执行外层查询,后执行子查询

数据库表结构设计,sql性能分析与优化


记得点击 在看、帮忙 转发哦