sql排序后取第⼀条数据_mysql002orderby的排序算法竟然是
这样的!
点击上⽅“java进阶架构师”,选择右上⾓“置顶”
20⼤进阶架构专题每⽇送达
前⾔
平常写业务的时候,我们经常需要对⼀些业务数据进⾏排序,例如点赞排名,浏览量排名等等。虽然这个字段很常⽤了,可能出于对服务器是 MySQL 的原因,使我们会胆怯或不想去了解它背后的执⾏流程,纯⿊箱⼦使⽤。但是如果不了解其内部机制,⼜何谈以优化使⽤?今天决定在这篇⽂章介绍⼀些 Order By 相关知识。
抛出本⽂问题
1. order by 的排序流程是什么?
2. order by 的排序算法是什么?
3. order by 的优化点在于什么?
解答疑问
排序流程
关于排序过程,MySQL 会通过判断 sort_buffer_size 来执⾏不同的排序流程。
sort_buffer_size 其实是 MySQL 的⼀个系统参数,它可以控制 MySQL 会在排序的时候分配的缓冲区⼤⼩,这个参数可以作⽤于 Global 或者 Session 级别。它的特点是允许动态变化,⽽且不针对特定的存储引擎。每每当有新的线程的时候,都会分配相应参数值的排序缓冲区⼤⼩。
了解完了这个参数值,我们可以介绍两种排序流程:
1. ⼀次排序
2. ⼆次排序
⼀次排序
⼀次排序不是⼀个专业术语,按照我的理解来解读,排序流程需要⼀次读取磁盘。
可能你会感觉困惑,那么来了解⼀下整个流程:
1. MySQL 会初始化排序缓冲区,然后读取⽬标 SQL 所有涉及到的字段(选择列,筛选列,排序列) 。
2. 如果筛选列是索引,则会根据索引进⾏查数据;如果⾮索引就全局扫描
3. 根据选择列将所需的数据加进排序缓冲区
4. 现在去寻第⼆条数据,所以它会重复去⾛ 2  ,3  步。直到所有符合筛选列的数据都被加载进缓冲区完。
5. ⽬前进⼊了排序阶段,根据排序列的要求,把排序缓冲区的数据加载进内存进⾏排序
6. 返回客户端
⼆次排序
看完了⼀次排序,或许你对⼆次排序也有⼀定的明⽩了。是的,⼆次排序流程需要对磁盘进⾏两次读取。
那我们还是对这个流程梳理:
1. MySQL 会初始化排序缓冲区,仅仅把 SQL 的⽬标表的主键ID以及排序列加载进去。
2. 根据筛选列进⾏数据的筛选。如果筛选列是索引,则会根据索引进⾏查数据;如果⾮索引就全局扫描
3. 假设查到了第⼀条数据,然后将这条数据的主键ID和排序列加载进内存。
4. 现在去寻第⼆条数据,所以它会重复去⾛ 2,3 步,直到获取了所有符合筛选列的数据。
5. ⽬前进⼊了排序阶段,根据排序列的要求,对排序缓冲区的数据进⾏排序并结果
6. 拿到了排序后的结果,根据每⼀条数据的主键ID回到原表扫描,获取到选择列的信息。
7. 返回给客户端
⽐对
/优点缺点
⼀次排序磁盘 IO 次数少,仅有⼀次读取,减轻内⼼的压⼒对排序缓冲区有更⼤的容量,还可能出现更⼤临时⽂件占⽤。
⼆次排序两次磁盘 IO,需要重新读取磁盘⼆次 IO,需要重新读取磁盘
排序算法
刚刚在排序流程中我们可以知道,实际进⾏排序的操作是放在内存的。其实上⾯的流程的都是在内存进⾏排序。但是实际应⽤场景上,有可能是⼀次性需要排序的数据集超出了内存范围;或者选择列太
多,,导致即使是少数据量也会内存爆满。所以当 MySQL ⾯对⼤数据量的情况下,会使⽤临时⽂件进⾏辅助存储已排序数据。
内存
内存当中主要使⽤的是⽐较常见的快速排序,基本思想是:通过⼀趟排序将要排序的数据分割成独⽴的两部分,其中⼀部分的所有数据都⽐另外⼀部分的所有数据都要⼩,然后再按此⽅法对这两部分数据分别进⾏快速排序,整个排序过程可以递归进⾏,以此达到整个数据变成有序序列。
内存+物理⽂件
由于内存不⾜的问题,MySQL 会对数据集进⾏多次读取,多次排序处理。假设⽬前内存已经满了,MySQL 会对内存的数据集使⽤快速排序,然后将结果保存到⼀个临时⽂件当中。然后 MySQL 会将内存清掉,重新根据筛选列再次读取数据。当内存再次爆满,然后会继续在内存进⾏排序,然后保存到临时⽂件。当数据完全准备好了,那么 MySQL 会使⽤多路归并排序对⽂件进⾏排序,原理跟归并排序中的⼆路归并⽐较类型,建议去了解⼀下。mysql删除重复的数据保留一条
优化点
1. 提⾼ sort_buffer_size。该值应该⾜够⼤,可以让⼤数据集也能加载进去,这样可以让 MySQL 减少
在排序的过程中对排序数据进⾏切
分,避免读写磁盘和合并⽂件。
2. 根据系统情况调节 max_length_for_sort_data,因为这个参数的⼤⼩会影响 MySQL 选择使⽤⼀次排序还是⼆次排序。当值⽐较⼩的
时候,会使⽤⼆次排序,相反使⽤⼀次排序。(如果数值设的太⾼,会导致磁盘活动太⾼,CPU 活动太低)。
3. 提⾼ read_rnd_buffer_size 可以提⾼读取的⾏数,减少的读的时间。
4. 尽量在 SQL 上使⽤索引满⾜ order by 的,避免执⾏⽂件排序操作时涉及的额外排序。⽽且有些通过索引扫描⽐通过表扫描更加廉
价。
————  e n d ————
微服务、⾼并发、JVM调优、⾯试专栏等20⼤进阶架构师专题请关注【Java进阶架构师】后在菜单栏查看。
看到这⾥,说明你喜欢本⽂
你的转发,是对我最⼤的⿎励!在看亦是⽀持↓

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。