MySQL排序内幕大揭秘:如何高效优化查询排序性能?

间隙填充
正睿科技  发布时间:2024-05-30 11:34:18  浏览数:558

关于正睿.png

前言

在日常的MySQL查询操作中,order bygroup by是非常常用的两个关键字。尽管它们都能对字段执行排序功能,但我们或许好奇,查询语句中的排序究竟是如何达成的?原来,这主要依据数据库中数据的实际状态来决定。例如,如果现有记录本身就是有序的,那么自然无需再额外进行排序;反之,若记录并未维持原有顺序,则必须进行相应的排序处理。

使用索引保证有序

针对首类场景,关键在于利用二级索引中索引列的内在顺序来直接获得已排序的结果集,免除额外的排序步骤。 以表a为例,若为其a2字段创建二级索引,该索引自然维持了a2值的有序性。

CREATE TABLE `a` (   `a1` int(11) NOT NULL AUTO_INCREMENT,   `a2` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL,   `a3` varchar(255) DEFAULT NULL,   PRIMARY KEY (`a1`),   KEY `idx_a2` (`a2`) ) ENGINE=InnoDB AUTO_INCREMENT=76 DEFAULT CHARSET=utf8;
select * from a order by a.a2 limit 10

当查询优化器采纳a2索引执行时,因其索引结构中a2字段的数据已是预排序状态,故无需额外负担进行数据排序的运算。

1717037547512045570.png

自然地,优化器也可能做出不同判断,放弃应用a2索引的情况亦存在,尤其是当评估到通过a2索引来回查找原始数据的开销过大时,它会选择直接进行全表扫描以求效率。

1717037607135006347.png

filesort

遭遇Using filesort情形时,意味着数据库将借助sort_buffer这一内存区域来完成结果集的排序工作。

sort_buffer是专为排序操作分配的内存空间,其可容纳查询涉及的所有字段,或仅保存参与排序的字段及主键,依据具体情况而定。

通过运行命令SHOW VARIABLES LIKE 'max_length_for_sort_data',可以查看决定sort_buffer存储策略的阈值。

如果查询请求的字段总大小不超过max_length_for_sort_data 配置的值,系统将把查询必需的所有字段内容置入sort_buffer。随后,仅就排序依据的列执行排序过程,直至排列完毕,直接反馈排序后的查询结果。

1717037948573082458.png

相反,若查询字段的总尺寸超过了max_length_for_sort_data 设定,策略则调整为仅记录排序字段与主键至sort_buffer中。排序操作完成后,系统需再度访问聚集索引以提取剩余所需查询字段,此步骤引入了额外的回表操作。

1717038071283075629.png

至于在sort_buffer内部的排序环节,若内存资源充裕,则排序全程在内存内完成。但若内存不足以承载排序数据,系统则会利用磁盘上的临时文件作为辅助工具,以实现大规模数据集的有效排序。

启用optimizer_trace特性可以追踪查询优化过程,以便判断是否使用了临时文件协助完成排序操作。

#开启优化器追踪 SET optimizer_trace='enabled=on'; #sql语句 select * from student order by student_name limit 10000; #查看优化器追踪的信息 SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G;

在进行排序时,采用的是高效的归并排序算法,这过程包括将数据分割成多个较小的部分独立排序,随后将这些已排序的小部分数据合并成完整有序的结果集。

这里有两个关键参数影响着排序效率:number_of_tmp_files 指定了在磁盘上可能使用的临时文件的最大数量,有助于并行处理大量数据排序;而 sort_buffer_size 则定义了分配给sort_buffer的内存容量,其大小直接影响到内存中能处理的数据量,从而影响到是否需要依赖磁盘临时文件以及整体排序性能。

1715411696945674002.png

在使用诸如ORDER BYGROUP BY这类涉及排序操作的语句时,构建恰当的索引尤为关键,能显著提升查询效率。

理想状况下,当待处理的数据规模适应于当前sort_buffer_size配置的内存大小时,排序操作可完全在内存中完成,无需额外的磁盘I/O操作。然而超出内存承载能力时,系统需要借助磁盘上的临时文件进行辅助排序。

总结

查询排序处理分两类情况:

索引直接有序:利用有序索引,避免额外排序。

索引无序或不足:使用sort_buffer,数据量适配内存则全字段存入排序;反之,仅存排序字段与主键,后续回表。内存不足时,借助磁盘临时文件实施归并排序。通过调整optimizer_trace监控辅助排序详情,优化策略包括创建适宜索引或调整sort_buffermax_length_for_sort_data参数(须谨慎)。

问题没解决? 我们帮您!

如果您在本文中未能找到解决当前问题的办法,不用担心——正睿专业技术支持团队随时待命

服务项目.png

获取更多帮助

文章来源:华为云社区 作者:菜菜的后端私房菜