关键点
- 如果排序字段不在索引列上,filesort有两种算法: mysql就要启动双路排序和单路排序
- 无过滤不索引
- order by非最左 filesort
- 顺序错 filesort
- 方向反 filesort
答案
- 首先要对sql进行分析检查必要的查询字段,过滤字段,排序字段是否按顺序创建好了索引
- 如果查询字段不在索引中可能会产生回表操作会导致filesort,降低性能
- 一定要有过滤字段不然不能使用索引
- 排序字段和索引顺序不一致会导致filesort,降低性能
- 多个字段排序时如果方向不一致也会导致filesort,降低性能
- 使用explain观察查询类型和索引利用情况
- 尽可能减少不必要的filesort
最左前缀法则示例
Where语句 | 索引是否被使用 |
---|---|
where a = 3 | Y,使用到a |
where a = 3 and b = 5 | Y,使用到a,b |
where a = 3 and b = 5 and c = 4 | Y,使用到a,b,c |
where b = 3 或者 where b = 3 and c = 4 或者 where c = 4 | N |
where a = 3 and c = 5 | 使用到a, 但是c不可以,b中间断了 |
where a = 3 and b > 4 and c = 5 | 使用到a和b, c不能用在范围之后,b断了 |
where a is null and b is not null | is null 支持索引 但是is not null 不支持,所以 a 可以使用索引,但是 b不一定能用上索引(8.0) |
where a <> 3 | 不能使用索引 |
where abs(a) =3 | 不能使用 索引 |
where a = 3 and b like ‘kk%’ and c = 4 | Y,使用到a,b,c |
where a = 3 and b like ‘%kk’ and c = 4 | Y,只用到a |
where a = 3 and b like ‘%kk%’ and c = 4 | Y,只用到a |
where a = 3 and b like ‘k%kk%’ and c = 4 | Y,使用到a,b,c |
一般性建议
对于单键索引,尽量选择过滤性更好的索引(例如:手机号,邮件,身份证)
在选择组合索引的时候,过滤性最好的字段在索引字段顺序中,位置越靠前越好。
选择组合索引时,尽量包含where中更多字段的索引
组合索引出现范围查询时,尽量把这个字段放在索引次序的最后面
尽量避免造成索引失效的情况
实验
删除索引
drop index idx_age_name_deptid on emp;
创建索引
CREATE INDEX idx_age_deptid_name ON emp (age,deptid,NAME);
无过滤不索引
EXPLAIN SELECT * FROM emp ORDER BY age,deptid;
EXPLAIN SELECT * FROM emp ORDER BY age,deptid LIMIT 10;
EXPLAIN SELECT age FROM emp where age>1000 ORDER BY age,deptid,name;
查询条件与筛选条件
const查询排序后回表操作,不会filesort
EXPLAIN SELECT * FROM emp WHERE age=45 ORDER BY age,deptid,NAME;
range查询,Using index condition 没有完全使用索引
EXPLAIN SELECT * FROM emp WHERE age>45 ORDER BY age,deptid,NAME;
range查询,Using where; Using index 完全使用索引
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY age,deptid,NAME;
顺序错 filesort
正常情况
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY age,deptid,NAME;
order by顺序变化会导致filesort
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY deptid,age,NAME;
order by非最左 filesort
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY deptid,NAME;
方向反 必排序
8.0为Backward index scan 倒序索引
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY age desc,deptid desc,NAME desc
方向反 产生filesort
EXPLAIN SELECT age FROM emp WHERE age>45 ORDER BY age desc,deptid desc,NAME asc;