数据库表结构设计(常见的数据库管理系统)

数据库表结构设计(常见的数据库管理系统)

差一点

原创

实战干货

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

1、数据库表结构设计,什么是概念模型、逻辑模型、物理模型

2、数据库表结构设计,什么是三范式,为什么要遵循三范式

3、数据库表结构设计,索引设计与优化

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

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

mysql给我们提供了解决办法,查看执行计划,使用EXPLAIN关键字可以模拟优化器执行SQL语句,从而知道MySQL是如何处理你的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;

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:十分重要的额外信息,最好情况就是Usingindex,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的原因,其中大部分的原因就是索引失效或者是没加索引导致的;

二、索引失效

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

索引失效情况总结:

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

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

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

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

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

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

7、or 会使索引失效;

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

速记口诀如下图:

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

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

发表评论

登录后才能评论