特别说明
本文总结自 极客时间 -> 每日一课 -> 为什么SQL语句使用了索引,但却还是慢查询
索引
- 区分主键索引(树)和非主键索引(树),数据放在主键索引树上
- 回表:根据主键到主键索引树上查询整行数据的过程
- 使用非主键索引,查询流程:查询非主键索引树 -> 回表
- 最左前缀原则
- 全表扫描:扫描整个主键索引树
- 让索引的过滤性好
- 查询的优化过程就是减少扫描和回表的过程
慢查询
- 慢查询日志:
slow.log
查询时间 > long_query_time
则进入慢查询日志- long_query_time 默认 10s
- 慢查询日志会包含两部分数据(有待需要验证)
使用索引并且查询时间 > long_query_time
的查询- 在
log_queries_not_using_indexes=ON
时,没有使用索引的查询
- 慢查询相关操作、分析及处理
相关 sql
create table t (
'id' int(11) NOT NULL,
'a' int(11) DEFAULT NULL;
'c' int(11) DEFAULT NULL;
PRIMARY KEY ('id'),
KEY 'a' ('a')
)ENGINE=InnoDB;
explain select * from t; # 没有使用索引
explain select * from t where id=2; # 使用了索引(查看列 `key:primary`)
explain select a from t; # 使用了索引 `a`,扫描整个索引(查看列 `key:a`)
# mysql 5.7 虚拟列
CREATE TABLE 't_people'(
'id' int(11) DEFAULT NULL,
'name' varchar(20) DEFAULT NULL,
'age' int(11) DEFAULT NULL,
'info' varchar(255) DEFAULT NULL,
'name_first' varchar(2) GENERATED ALWAYS AS (left('name',1)) VIRTUAL,
KEY 'name_first' ('name_first','age')
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
SELECT * FROM t_people WHERE name_first='张' and age=8;
show variables like 'long_query_time'; # default 10s
set global long_query_time=0.1
show variables like 'log_queries_not_using_indexes';
set global log_queries_not_using_indexes = 0;