五、mysql——常见sql语句优化
Order by与Group by优化
case1
EXPLAIN SELECT * FROM employees WHERE name=lilei AND position =manager order by age;
分析:根据最左前缀原则,中间字段不能断,所以只使用了‘name’索引;从Extra字段不是 fileosrt可以看出来age索引列也参与了排序过程。
case2
EXPLAIN SELECT * FROM employees WHERE name=lilei order by position
分析:使用了‘name’索引,由于用了position进行排序,跳过了age,所以出现了效率比较低的Using filesort,需要优化。
case3
EXPLAIN SELECT * FROM employees WHERE name=lilei order by age,position
分析:查找用了‘name’索引,排序用了‘age’和‘position’;
case4
EXPLAIN SELECT * FROM employees WHERE name=lilei order by position,age
分析:查找走了‘name’索引,排序的话因为position和age与索引的顺序不一致,所以导致走了低效率的fileosrt,需要优化。
case5
EXPLAIN SELECT * FROM employees WHERE name=lilei and age=18 order by position,age
分析:这里age是个常量,所以可以使用索引排序
case6
EXPLAIN SELECT * FROM employees WHERE name=zhuge ORDER BY age asc,position desc;
分析:虽然排序字段顺序与索引顺序一样,order by默认是升序,这里position是降序排序,所以还是走了低效率的filesort这种形式。 但是在Mysql8针对这种形式进行了优化。
case7
EXPLAIN SELECT * FROM employees WHERE name in (lilei,zhuge) ORDER BY age ,position;
分析:对于排序来说,多个相等的条件也是范围查询。
case8
EXPLAIN SELECT * FROM employees WHERE name >a ORDER BY name
分析:name>a’查询出来的数据量比较大, 导致会走全表扫描。 优化:覆盖索引
EXPLAIN SELECT name,age,position FROM employees WHERE name >a ORDER BY name;
优化总结:
1、mysql支持两种排序方式filesort和index,Using index是扫描索引完成排序,index效率高,filesort效率低; 2、order by 满足两中情况会走索引: (1)order by 语句使用索引最左前列; (2)使用where字句与order by字句组合满足索引最左前缀; 3、尽量在索引列上完成排序,遵循索引建立时的最左前缀法则; 4、能使用覆盖索引,尽量走覆盖索引; 5、group by 与order by很类似,其实质是先排序后分组,注意遵守最左前缀原则。
Using filesort的排序方式可以分为单路排序和双路排序
- 双路排序:是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行指针信息,然后在sort buffer 中进行排序。 2)单路排序:是一次性取出满足条件行的所有字段,然后在sort buffer中进行排序。
索引设计原则
代码先上,索引后上
联合索引尽量覆盖条件
不要在小基数字段上建立索引
长字符串我们可以建立前缀索引
where 和order by冲突时,优先where
因为where可以过滤大量数据,剩下的数据在排序,可以提高效率。
