`

mysql中的order by

阅读更多
今天学习时才发现,原来mysql中的order by的道理是如下的,涉及到两种算法
下面笔记之.
mysql把需要排序的地方都叫filesort, 名字上看有个file在里面,但不一定与文件有关, 可能就是在内存完成的排序。

MySQL 有二个 filesort 算法, 第一个方法(原始方法)只使用了ORDER BY中指定的字段。第二个方法(改进的方法)不仅使用ORDER BY中指定的字段,还是用了查询中所涉及到的所有的字段。

优化器决定选择哪个filesort 算法, 除了查询中涉及到TEXT或者BLOCk字段外,它通常使用改进的算法,当查询中涉及到TEXT或者BLOCk字段时,通常使用原始的方法。

原始的 filesort 算法的工作机制大体是(典型的外排算法):

1. 通过主键扫描或表扫描读出所有的数据记录,不相配WHERE条件的记录被跳过。

2. 对于每条记录,储存一对信息(主键和指向记录的指针)到查询缓冲区,缓冲区的大小是 sort_buffer_size 系统变量控制的。

3. 一旦缓冲区满了,对缓冲区中的数据做一次 qsort(快速排序)并把排序结果保存到一个临时文件。(如果所有记录信息能放到缓冲区中,就没有必要存到临时文件了)

4. 重复前述的步骤直到所有的记录都处理了完。

5. 每在合并缓冲区中做多路合并, 并把合并后的结果输出到另外一个临时文件

6. 重复多路合并排序, 直到所有的记录信息能分到15个以内的有序集合。

7. 在最后多路合并中,只有指向记录的指针被写到一个结果文件。

8. 根据结果文件中的记录指针的读取出记录放到返回集合中, 这个结果缓冲区的大小是 read_rnd_buffer_size 系统变量设置的。

这个排序算法有几个问题值得注意:

1. 它需要读取记录两次:第一次是执行的WHERE时候,第二次是在对key进行排序之后。 尽管第一次是读取时记录是连续读取的(比如表扫描), 第二次就是随机读取了。(这时候键值是有序的了,但是记录还不是)

2. 使用到了快速排序,也就是说,排序结果是不稳定的

改进的 filesort 算法在原始的算法的基础上做了一些优化: 在排序时,不只是对键值进行操作,还带有记录位置和查询中需要的字段信息,这避免两次都记录。改进的 filesort 算法的工作机制:

1. 读取符合WHERE条件的记录。

2. 对于每条记录,把键值, 记录位置和查询所需要的字段记录到一个元组中。

3. 根据键值对元组进行排序

4. 从排序后的元组中取得返回结果, 直接从排序好的元组中读取即可, 避免了第扫表。

在改进的 filesort 算法中,元组比原始方法中用的信息对(键值和记录指针)所占得空间要多,因此同样大的sort_buffer_size放的记录数更少,因此可能会导致更多的I/O操作,从而使得效率更慢,而不是更快。为了避免这种负面优化,只有当元组中存储的额外字段信息的大小不超过 max_length_for_sort_data 系统变量时才使用改进的排序算法。(设定太高的max_length_for_sort_data是明显症状是高的磁盘I/O活动和低的处理器使用率。)

因此, 如果想要提高ORDER BY的速度,尽量使MySQL使用索引而不是通过额外的排序工作来排序。如果无法使用索引,试一下改变一些系统参数:

1. 增加 sort_buffer_size 变数的大小, 这个参数控制着进行排序时的缓冲区的大小, 这个参数越大,进行归并排序的次数就会少

2. 增加 read_rnd_buffer_size 变数的大小, 这个参数控制着用来存放扫表记录存放缓冲额大小,这个参数越大, 能存放的记录数会多

3. 在满足业务需要的前提下把字段声明的尽可能的小,这样排序时占的内存也会少;比如, 如果字段的值无法超过 16个字符的话,VARCHAR(16) 比VARCHAR (200) 好。

4. 把 tmpdir 设置成有大量的自由空间的专用的 filesystem 。另外,这选项接受的值是可以使由”:”(UNIX上)或”;”( Windows, NetWare, and OS/2)分隔的若干个路径,在使用时, mysql会用轮转法来依次使用这些路径,因此, 可以考虑设置多个路径来提高排序时的i/o速度。当然,路径应该是给位于不同的物理磁盘之上的 filesystems, 而不是在相同的磁盘片上的不同的目录。


5 使用算法2的前提是,列长度的值小于max_length_for_sort_data


5. 在需要排序的字段中, 尽量避免涉及到TEXT和BLOB字段;如果有这些字段,第一系统无法使用改进的排序算法,第二,系统在处理时需要分配更多的内存来存放这些字段(在排序处理时, 每条记录分配的空间是一样大,因此系统会根据选取最大可能的长度来分配空间, 这个通常会很低效,因此,有一个变量max_sort_length来限制排序时BLOB或TEXT字段的长度);当确实需要用到这些字段时, 考虑用SUBSTR进行截取;

6. 设置合适的max_length_for_sort_data, 注意mysql在通过这个值控制排序算法的选择时,对于VARCHAR字段使用的最大长度,而不是实际用到的长度。

分享到:
评论

相关推荐

    深入解析mysql中order by与group by的顺序问题

    mysql 中order by 与...要查出group by中最大的或最小的某一字段使用 max或min函数。例:select sum(click_num) as totalnum,max(update_time) as update_time,count(*) as totalarticle from article_detail where

    mysql中order by与group by的区别

    在MySQL数据库中,`ORDER BY` 和 `GROUP BY` 是两个非常重要的子句,它们各自在数据处理中扮演着不同的角色。理解它们的区别对于优化查询性能和获取所需数据至关重要。 `ORDER BY` 子句主要用于对查询结果进行排序...

    MySQL中Order By多字段排序规则代码示例

    在MySQL数据库中,`ORDER BY`子句用于对查询结果进行排序。在处理多字段排序时,MySQL遵循特定的规则来确定数据的排列顺序。本文将深入探讨这些规则,并通过代码示例进行解释。 首先,单字段排序是相对简单的。假设...

    Mysql中order by、group by、having的区别深入分析

    在MySQL数据库中,ORDER BY、GROUP BY 和 HAVING 子句是SQL查询中用于数据处理的关键组成部分,它们各自承担不同的任务,以帮助我们从数据库中提取有用的信息。 ORDER BY 子句主要用于对查询结果集进行排序。当你...

    MySQL中union和order by同时使用的实现方法

    MySQL中union和order by是可以一起使用的,但是在使用中需要注意一些小问题,下面通过例子来说明。首先看下面的t1表。 1、如果直接用如下sql语句是会报错:Incorrect usage of UNION and ORDER BY。 SELECT * FROM ...

    MySQL order by性能优化方法实例

    一 MySQL中order by的原理  1 利用索引的有序性获取有序数据  当查询语句的 order BY 条件和查询的执行计划中所利用的 Index 的索引键(或前面几个索引键)完全一致,且索引访问方式为 rang,ref 或者 index 的时候,...

    深度分析mysql GROUP BY 与 ORDER BY

    本文就和大家一起深入研究下mysql中group by与order by.下面是我模拟我的内容表   我现在需要取出每个分类中最新的内容 select * from test group by category_id order by `date` 结果如下   明显。这不是我想...

    mysql中提高Order by语句查询效率的两个思路分析

    在MySQL数据库中,Order by语句的使用频率是比较高的。但是众所周知,在使用这个语句时,往往会降低数据查询的性能。因为可能需要对数据库的记录进行重新排序。在这篇文章中,笔者就谈谈提高Order By语句查询效率的...

    Mysql联合查询UNION和Order by同时使用报错问题的解决办法

    因此,常常出现这样的错误 代码如下:select * from [IND] where INDID>10unionselect * from [IND] where INDID<9>10 order by INDID descunionselect * from [IND] where INDID<9 order by INDID desc此时就出现...

    MySQL Order By索引优化方法

    MySQL的`ORDER BY`和`GROUP BY`子句在执行查询时,对于性能的影响是显著的,尤其是在大数据量的表中。为了提高查询效率,索引优化显得至关重要。本文将详细介绍如何利用索引来优化`ORDER BY`操作。 首先,MySQL在...

    mysql中count(), group by, order by使用详解

    在MySQL中,`COUNT()`, `GROUP BY`, 和 `ORDER BY` 是三个非常重要的SQL语句组成部分,它们各自承担着不同的职责,同时也常被结合在一起使用以满足复杂的数据查询需求。 `COUNT()` 是一个聚合函数,它用于计算指定...

    mysql分组取每组前几条记录(排名) 附group by与order by的研究

    –按某一字段分组取最大(小)值所在行的数据 代码如下: /* 数据如下: nameval memo a 2 a2(a的第二个值) a 1 a1–a的第一个值 a 3 a3:a的第三个值 b 1 b1–b的第一个值 b 3 b3:b的第三个值 b 2 b2b2b2b2 b 4 b4b4 b ...

    mysql order by limit 的一个坑.docx

    解决这个问题的方法是:在 ORDER BY 列中包含一个索引列,例如,我们可以在 ORDER BY 列中加上主键 id,这样可以确保 MySQL 按照正常的排序顺序返回记录。 MySQL 的官方文档中也提到这个问题,原文如此描述: “If...

    activiti5.9修复mysql order by 排序bug

    activiti5.9修复mysql order by 排序bug 详情见博客地址:http://blog.csdn.net/qq413041153/article/details/7740773#comments

    MySQL数据库中group by语句与update语句的用法研究.pdf

    MySQL 数据库中 group by 语句与 update 语句的用法研究 本论文对 MySQL 数据库中的 group by 语句和 update 语句进行了深入研究,讨论了这些语句在数据库查询和修改中的应用,并给出了具体的解决方案。 一、MySQL...

Global site tag (gtag.js) - Google Analytics