MySQL高级 之 order by、group by 优化

order by示例

示例数据:

Case 1

Case 2

Case 3

Case 4

结论:order by子句,尽量使用Index方式排序,在索引列上遵循索引的最佳左前缀原则。
复合(联合)索引形如 key (‘A1’,’A2’,’A3’ ),排序的思路一般是,先按照A1来排序,A1相同,然后按照A2排序,以此类推,这样对于(A1),(A1,A2), (A1,A2,A3)的索引都是有效的,但是对于(A2,A3)这样的索引就无效了。尽量避免因索引字段的缺失 或 索引字段顺序的不同 引起的FileSort排序。

order by 总结

FileSort排序算法

算法一:双路排序算法

只利用ORDERBY子句中包括的列对象进行排序(适用于有BLOB、TEXT类型的列对象参与的排序)

MySQL4.1之前的排序算法,完整实现过程如下:

1) 按索引键或全表扫描的方式,读取所有的元组,不匹配WHERE子句的元组被跳过;第一步需要从存储读入数据,引发I/O操作。

2) 对于每一行,在缓冲区中存储一对值(对值,包括排序关键字和元组指针)。缓冲区的大小是系统变量的sort_buffer_size设定的值。

3) 当缓冲区已满,运行快排算法(快速排序,qsort)对一个块中的数据进行排序,将结果存储在一个临时文件。保存一个指向排序后的块的指针(如果第二步所说的对值都能被缓冲区容纳,则不会创建临时文件)。

4) 重复上述步骤,直到所有的行已经被读取。

5) 执行一个多路归并操作(操作对象是第三步生成的每一个有序的块)汇集到“MERGEBUFF域”,然后存放到在第二个临时文件中。重复操作,直到第一个文件的所有块归并后存入到第二个文件;“MERGEBUFF域”是代码sql_sort.h中定义的宏,值为7。

6) 重复以下操作(第7步和第8步),直到留下少于“MERGEBUFF2域”标明的块数为止;“MERGEBUFF2域”是代码sql_sort.h中定义的宏,值为15。

7) 在最后一次多路归并操作中,把元组的指针(排序关键字的最后部分)写入到一个结果文件。

8) 在结果文件中,按照排列的顺序使用元组指针读取元组(为了优化这项操作,MySQL读入元组指针进入一个大的块,对块中元组指针进行排序而不是直接对数据排序,然后再用有序的元组指针获取元组到元组缓存,元组缓冲区的大小由read_rnd_buffer_size参数控制)。第8步需要从存储读入数据,引发I/O操作。

算法二:单路排序算法

除利用ORDERBY子句中包括的列对象外,还利用查询目标列中的所有列对象进行排序(适用于除BLOB、TEXT类型外的所有的其他类型的排序)

MySQL4.1之后出现的改进算法,减少一次I/O,需要增加缓冲区大小容纳更多信息。其具体实现过程如下:

1) 获取与WHERE子句匹配的元组。这一步需要从存储读入数据,引发I/O操作。

2) 对于每一个元组,记录排序键值、行的位置值、查询所需的列。这一步记录更多内容,需要更大缓存,内存存储一条元组的信息的长度比算法一的“对值”大许多,这可能引发排序速度问题(排序对象的长度变长,但是内存有限,所以就需把一次内存排序变为多次,进而影响排序的速度),为了控制这个问题,MySQL引入一个参数“max_length_for_sort_data”,如果这一步得到的元组长度大于这个值,则不使用算法二。需要MySQL的使用者特别注意的是,在排序中,如果存在“很高磁盘I/O和很低的CPU利用率”的现象,则需要考虑调整“max_length_for_sort_data”的大小以变更换排序算法。

3) 按照排序的键值,对元组(元组是第二步的结果)进行排序。

算法二直接从缓冲区中的排序的元组中获取有序的列信息等(查询的目的对象),而不是第二次访问该表读取所需的列。相比算法一减少一次I/O。

FileSort优化策略

当无法使用索引列排序时,为了提高Order By的速度,应该尝试一下优化:
1、避免使用 “select * ” 。查询的字段越多导致元组长度总合可能

超过max_length_for_sort_data的设置,导致无法使用单路排序算法,只能用双路排序算法。
超过sort_buffer_size的设置,超出后会创建tmp文件进行合并,导致多次IO
2、适当增大sort_buffer_size参数的设置

3、适当增大max_length_for_sort_data参数的设置

group by 示例

示例:

group by 总结

group by与order by的索引优化基本一样,group by实质是先排序后分组,也就是分组之前必排序,遵照索引的最佳左前缀原则可以大大提高group by的效率。

当无法使用索引列排序时,适当增大sort_buffer_size参数 + 适当增大max_length_for_sort_data参数可以提高filesort排序的效率。注意:可能会出现Using temporary,也就是说mysql在对查询结果排序时使用了临时表。

where高于having,能写在where限定条件中的就尽量写在where中。
---------------------
作者:走慢一点点
来源:CSDN
原文:https://blog.csdn.net/wuseyukui/article/details/72627667
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/maohuidong/p/10983096.html

时间: 2024-10-06 06:14:48

MySQL高级 之 order by、group by 优化的相关文章

mysql ORDER BY,GROUP BY 和DISTINCT原理

前言 除了常规的Join语句之外,还有一类Query语句也是使用比较频繁的,那就是ORDERBY,GROUP BY以及DISTINCT这三类查询.考虑到这三类查询都涉及到数据的排序等操作,所以我将他们放在了一起,下面就针对这三类Query语句做基本的分析. ORDER BY 的实现与优化 在MySQL中,ORDERBY的实现有如下两种类型: 一种是通过有序索引而直接取得有序的数据,这样不用进行任何排序操作即可得到满足客户端要求的有序数据返回给客户端: 另外一种则需要通过MySQL的排序算法将存储

MySQL高级知识(四)——Explain

前言:explain(执行计划),使用explain关键字可以模拟优化器执行sql查询语句,从而知道MySQL是如何处理sql语句.explain主要用于分析查询语句或表结构的性能瓶颈. 注:本系列随笔如无特殊说明都MySQL版本都为5.7.22. 1.explain的作用 通过explain+sql语句可以知道如下内容: ①表的读取顺序.(对应id) ②数据读取操作的操作类型.(对应select_type) ③哪些索引可以使用.(对应possible_keys) ④哪些索引被实际使用.(对应k

Mysql占用过高CPU时的优化手段

Mysql占用CPU过高的时候,该从哪些方面下手进行优化?占用CPU过高,可以做如下考虑:1)一般来讲,排除高并发的因素,还是要找到导致你CPU过高的哪几条在执行的SQL,show processlist语句,查找负荷最重的SQL语句,优化该SQL,比如适当建立某字段的索引:2)打开慢查询日志,将那些执行时间过长且占用资源过多的SQL拿来进行explain分析,导致CPU过高,多数是GroupBy.OrderBy排序问题所导致,然后慢慢进行优化改进.比如优化insert语句.优化group by

第三章 MySQL高级查询(一)

第三章 MySQL高级查询(一) 一.SQL语言的四个分类 1.       DML(Data Manipulation Language)(数据操作语言):用来插入,修改和删除表中的数据,如INSERT,UPDATE,DELECT. 2.       DDL(Data Definition Language)(数据定义语言):创建或删除数据库对象操作,有CREATE,DROP,ALTER三个语法组成. 3.       DQL (STructured Query Language)(数据查询语

mysql如何查看索引使用情况以及优化 - guols0612

mysql中支持hash和btree索引.innodb和myisam只支持btree索引,而memory和heap存储引擎可以支持hash和btree索引 我们可以通过下面语句查询当前索引使用情况: show status like '%Handler_read%'; +-----------------------+-------+| Variable_name | Value |+-----------------------+-------+| Handler_read_first | 0

我的MYSQL学习心得(十六) 优化

这一篇主要介绍MYSQL的优化,优化MYSQL数据库是DBA和开发人员的必备技能 MYSQL优化一方面是找出系统瓶颈,提高MYSQL数据库整体性能:另一方面需要合理的结构设计和参数调整,以提高 用户操作响应的速度:同时还有尽可能节省系统资源,以便系统可以提供更大负荷的服务 如果大家看过我写的两篇文章,那么学习MYSQL的索引就不会太难,因为是相通的 SQLSERVER聚集索引与非聚集索引的再次研究(上) SQLSERVER聚集索引与非聚集索引的再次研究(下) 其实MYSQL也有SQLSERVER

MySQL高级知识点

MySQL高级知识初识 一.视图: 1.什么是视图: 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. SELECT * FROM ( SELECT nid, NAME FROM tb1 WHERE nid > 2 ) AS A WHERE A. NAME > 'xkj'; 2.创建视图 --格式:CREATE VIEW 视图名称 AS SQL语句 CREATE VIEW v1 AS SE

搞定linux上MySQL编程(三):MySQL高级语法

[版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途] 本节介绍Mysql高级语法,包括试图.存储过程.索引等,通过使用试图.触发器等来优化数据库设计和查询技术,提高数据处理能力与效率. 视图操作: 视图是一个虚拟表,内容由查询定义.视图并不在数据库中以存储的数据值集形式存在,行和列数据来源于定义视图的查询所引用的表,且在引用试图时动态生成.从数据库系统外部来看,视图就如同一张表一样,对表能够进行的一般操作的哦可以应用于视图,例如

Mysql LIMIT如何正确对其进行优化

Mysql LIMIT如何正确对其进行优化 2010-05-17 17:09 佚名 博客园 字号:T | T 我们今天主要和大家分享的是Mysql LIMIT简单介绍以及如何进行优化的相关内容的描述,以下就是正文的主要内容描述. AD:51CTO 网+首届APP创新评选大赛火热启动——超百万资源等你拿! 以下的文章主要是对Mysql LIMIT简单介绍,我们大家都知道LIMIT子句一般是用来限制SELECT语句返回的实际行数.LIMIT取1个或是2个数字参数,如果给定的是2个参数,第一个指定要返