MySQL索引分析和优化
2021-08-23 17:34:09 2 举报
AI智能生成
MySQL索引分析和优化
作者其他创作
大纲/内容
索引分析和优化
EXPLAIN
MySQL提供了一个EXPLAIN命令,它可以对Select语句进行分析,并输出Select执行的详细信息,供开发人员有针对性的优化
输出
select_type
表示查询的类型
常用值
SIMPLE
表示查询语句不包含子查询或union
PRIMARY
表示此查询是最外层的查询
UNION
表示此查询是Union的第二个或后续的查询
DEPEDENT UNION
表示Union中的第二个或后续的查询语句,使用了外面查询结果
UNION RESULT
Union的结果
SUBQUERY
子查询语句
DEPENDENT SUBQUERY
子查询语句依赖外层查询的结果
最常见的查询类型是SIMPLE,表示查询没有子查询也没用到Union查询
type
表示存储引擎查询数据采用的方式,比较重要的一个属性,通过它可以判断出查询是全表扫描还是基于索引的部分扫描
常用值如下,从上至下效率依次增强
ALL
表示全表扫描,性能最差
index
表示基于索引的全表扫描,先扫描索引再扫描全表数据
range
等
ref
表示使用非唯一索引进行单值查询
eq_ref
一般情况下出现在多表join查询,表示前面表的每一个记录,只能匹配后面表的一行结果
const
表示使用主键或唯一索引做等值查询,常量查询
NULL
表示不用访问表,速度最快
key_len
表示查询使用了索引的字节数量,可以判断是否全部使用了组合索引
计算规则
字符串类型
字符串长度跟字符集有关:latin1:1,gbk:2、utf8:3、utf8mb4:4
char(n):n*字符集长度
varchar(n):n*字符集长度+2字节
数值类型
TINYINT:1字节
SMALLINIT:2字节
MEDIUMINT:3字节
INT、FLOAT:4字节
BIGINT、BOUBLE:8字节
时间类型
DATE:3字节
TIMESTAMP:4字节
DATETIME:8字节
字段类型
NULL属性占用1字节,如果字段设置了NOT NULL,则没有此项
extra
表示很多额外的信息,各种操作会在Extra提示相关信息
常见有
Using where
表示查询需要通过索引回表查询数据
Using Index
表示查询需要通过索引,索引就可以满足所需数据
Using filesort
表示查询出来的结果需要额外排序,数据量小在内存,大的话在磁盘,因此有Using filesort建议优化
Using temproary
查询使用到了临时表,一般出现于去重、分组等操作
possible_keys
表示查询时能够使用到的索引,注意并不一定会真正使用,显示的是索引名称
key
表示查询时真正使用到的索引,显示的是索引名称
rows
MySQL查询优化器会根据统计信息,估算SQL要查询到结果需要扫描多少行记录
原则上rows是越少效率越高,可以直观的了解SQL效率高低
回表查询
辅助索引的叶子节点存储的是主键值和索引字段值,通过辅助索引无法直接定位行记录,通常情况下,需要扫描两遍索引树
先通过辅助索引定位主键值,然后再通过聚集索引定位行记录,这就叫做回表查询,它的性能比扫一遍索引树低
通过索引查询主键值,然后再去聚集索引查询记录信息
覆盖索引
explain的输出结果extra字段为Using Index时,能够触发索引覆盖
只需要在一颗索引树上就能获取SQL所需的所有列数据,无需回表,速度更快,这就叫做覆盖索引
实现的最常见方法
将被查询的字段,建立到组合索引
最左前缀原则
复合索引使用时遵循最左前缀原则,即最左优先
查询中使用到最左边的列,那么查询就会使用到索引,如果从索引的第二列开始查找,索引将失效
Like查询
MySQL在使用Like模糊查询时,索引是可以被使用的,只有把%字符写在后面才会使用到索引
Null查询
对于MySQL来说,Null是一个特殊值,从概念上讲,Null意味着“一个未知值”,它的处理方式与其他值有些不同
不能使用=、这样的运算符
对Null做算术运算的结果都是Null
count时不会包括Null行
Null比空字符串需要更多的存储空间
....
Null列需要增加额外的空间来记录其值是否为Null。对于MyISAM表,每一个空列额外占用一位,四舍五入到最接近的字节
虽然MySQL可以在含有Null的列上使用索引,但Null和其他数据是有区别的,不建议列上允许为Null
最好设置Not Null,并设置默认值
索引和排序
MySQL查询支持filesort和index两种方式排序
filesort
先把结果查出,然后在缓存或磁盘进行排序操作,效率较低
指利用索引自动实现排序,不需另做排序操作,效率会比较高
filesort有两种排序算法
双路排序
需要两次磁盘扫描读取,最终得到用户数据
第一次将排序字段读取出来,然后排序,第二次去读取其他字段数据
单路排序
从磁盘查询所需的所有列数据,然后在内存排序将结果返回
如果查询数据超出缓存sort_buffer,会导致多次磁盘读取操作,并创建临时表,最后产生了多次IO,反而会增加负担
解决方案
少使用select *
增加sort_buffer_size容量
增加max_length_for_sort_data容量
index场景
Order by 子句索引列组合满足索引最左前列
where子句 + Order By子句索引列组合满足索引最左前列
filesort场景
对索引列同时使用了ASC和DESC
Where子句和Order By子句满足最左前缀,但Where子句使用了范围查询(、in)
Order By 或者 Where + Order By索引列没有满足索引最左前列
使用了不同的索引,MySQL每次只采用一个索引,Order By涉及了两个索引
Where 子句和Order By子句,使用了不同的索引
Where 子句或Order By子句索引列使用了表达式,包括函数表达式
查询优化
慢查询
定位
开启慢查询日志
show variables like '%slow_query_log%'
long_query_time
指定慢查询的阈值,单位s,如果SQL执行时间超过阈值,就属于慢查询记录到日志文件中
log_queries_not_using_indexes
表示会记录没有使用索引的查询SQL,前提是slow_query_log值为ON,否则不会奏效
查看慢查询日志
文本查看
直接使用文本编辑器打开慢查询日志
主要包含
time
日志记录的时间
User@host
执行的用户/主机
Query_time
执行的时间
Lock_time
锁表时间
Rows_sent
发送给请求方的记录数,结果数量
Rows_examined
语句扫描的记录条数
Set timestamp
语句执行的时间点
执行的具体SQL语句
使用mysqldumpslow查看
MySQL提供了一个慢查询日志分析工具mysqldumpslow,可以通过该工具分析慢查询日志
在MySQL bin目录下执行命令
perl mysqldumpslow.pl --help
运行如下命令查看慢查询日志信息
使用第三方分析工具
pt-query-digest
mysqlsla
优化
索引和慢查询
MySQL判断一条语句是否为慢查询,主要依据SQL语句的执行时间,对比long_query_time
查询是否使用索引,只是表示一个SQL语句的执行过程,而是否为慢查询,是由它执行的时间决定的
使用索引时,不要只关注是否起作用,应该关心索引是否减少了查询扫描的数据行数
对于一个大表,不止要创建索引,还要考虑索引过滤性,过滤性好,执行速度才会快
提高索引过滤性
索引过滤性与索引字段、表的数据量、表设计结构都有关系
根据SQL增加索引
还可以使用MySQL 5.7引入的虚拟列,做联合索引
原因总结
全表扫描
explain分析,type=ALL
全索引扫描
explain分析,type=INDEX
索引过滤性不好
靠索引的字段选形,数据量和状态、表设计
频繁的回表查询开销
尽量少用select *,尽量使用覆盖索引
分页查询
一般性分页
使用简单的limit子句就可以实现
如果偏移量固定,返回记录数对执行时间
随着记录量越大,所花费的时间也会越来越多
如果查询偏移量变化,返回记录数固定对执行时间
随着偏移量增大,查询时间急剧增加
优化方案
step1:利用覆盖索引优化
step2:利用子查询优化
MySQL
0 条评论
回复 删除
下一页