MySQL之索引优化(二)


小表驱动大表

在这里插入图片描述

ORDER BY 优化

模拟数据

create table tblA(
#id int primary key not null auto_increment,
age int,
birth timestamp not null
);

insert into tblA(age, birth) values(22, now());
insert into tblA(age, birth) values(23, now());
insert into tblA(age, birth) values(24, now());

create index idx_A_ageBirth on tblA(age, birth);

查看执行计划

案例A

EXPLAIN SELECT * FROM tblA WHERE age > 20 ORDER BY age
EXPLAIN SELECT * FROM tblA WHERE age > 20 ORDER BY age,birth
EXPLAIN SELECT * FROM tblA WHERE age > 20 ORDER BY birth
EXPLAIN SELECT * FROM tblA WHERE age > 20 ORDER BY birth,age
EXPLAIN SELECT * FROM tblA WHERE birth > '2021-02-19 22:45:00' ORDER BY birth
EXPLAIN SELECT * FROM tblA WHERE birth > '2021-02-19 22:45:00' ORDER BY age

在这里插入图片描述

案例B

EXPLAIN SELECT * FROM tblA ORDER BY age ASC,birth DESC 

在这里插入图片描述

结论

  • MySQL支持两种方式的排序,index和filesort。index效率高,它是指扫描索引本身完成排序,filesort效率低。
  • ORDER BY子句,尽量使用Index方式排序,避免filesort方式排序。
  • ORDER BY子句满足两种情况,会使用index排序,一是ORDER BY子句采用遵照最佳左前缀法则,二是where条件字段和ORDER BY子句组合起来,满足最佳左前缀法则
    排序分组优化

MySQL的排序算法

当发生 Using filesort 时,MySQL会根据自己的算法对查询结果进行排序

双路排序

  • MySQL 4.1 之前是使用双路排序,字面意思就是两次扫描磁盘,最终得到数据,读取行指针和 order by 列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据输出.
  • 从磁盘取排序字段,在 buffer 进行排序,再从磁盘取其他字段
    简单来说,取一批数据,要对磁盘进行了两次扫描,众所周知,I\O 是很耗时的,所以在 mysql4.1 之后,出现了第二种改进的算法,就是单路排序

单路排序

  • 从磁盘读取查询需要的所有列,按照 order by 列在 buffer 对它们进行排序,然后扫描排序后的列表进行输出, 它的效率更快一些,避免了第二次读取数据。并且把随机 IO 变成了顺序 IO,但是它会使用更多的空间, 因为它把每一行都保存在内存中了

存在的问题

  • 在 sort_buffer 中,方法 B 比方法 A 要多占用很多空间,因为方法 B 是把所有字段都取出, 所以有可能取出的数据的总大小超出了 sort_buffer 的容量,导致每次只能取 sort_buffer 容量大小的数据,进行排序(创建 tmp 文件,多 路合并),排完再取取 sort_buffer 容量大小,再排……从而多次 I/O。也就是本来想省一次 I/O 操作,反而导致了大量的 I/O 操作,反而得不偿失

如何优化

  • 增大sort_buffer_size参数的设置

    不管用哪种算法,提高这个参数都会提高效率,当然,要根据系统的能力去提高,因为这个参数是针对每个进程的 1M-8M 之间调整

  • 增大max_length_for_sort_data参数的设置

    mysql 使用单路排序的前提是排序的字段大小要小于 max_length_for_sort_data, 提高这个参数,会增加使用改进算法的概率。

    但是如果设的太高,数据总容量超出 sort_buffer_size 的概率反而会增大, 就会出现高频磁盘 I/O低的处理器使用率。(1024-8192 之间调整)
    总结

    扫描二维码关注公众号,回复: 12614477 查看本文章
  • 减少 select 后面的查询的字段(少用select *)

    查询的字段减少,缓冲就能容纳更多的内容,也就相当于间接增大了sort_buffer_size

总结A

在这里插入图片描述

总结B

在这里插入图片描述

GROUP BY 优化

GROUP BY 优化和ORDER BY大致类似
在这里插入图片描述

  • 要想在排序时使用索引,避免 Using filesort,可以采用索引覆盖
  • ORDER BY /GROUP BY后面字段的顺序要和复合索引的顺序完全一致
  • ORDER BY /GROUP BY后面的索引必须按照顺序出现,排在后面的可以不出现
  • 要进行升序或者降序时,字段的排序顺序必须一致。不能一部分升序,一部分降序,可以都升序或者都降序
  • 如果复合索引前面的字段作为常量出现在过滤条件中,排序字段可以为紧跟其后的字段

猜你喜欢

转载自blog.csdn.net/single_0910/article/details/113873323