下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

MySQL order by性能优化方法实例

作者:课课家教育     来源: http://www.kokojia.com点击数:777发布时间: 2017-08-24 08:30:52

标签: 数据库MySQLorder by语句

  工作过程中,各种业务需求在访问数据库的时候要求有orderby排序。有时候不必要的或者不合理的排序操作很可能导致数据库系统崩溃。如何处理好orderby排序呢?本文从原理以及优化层面介绍order by~~

工作过程中,各种业务需求在访问数据库的时候要求有orderby排序。有时候不必要的或者不合理的排序操作很可能导致数据库系统崩溃。如何处理好orderby排序呢?本文从原理以及优化层面介绍order by~~

  一、MySQL中order by的原理

  1.利用索引的有序性获取有序数据

  当查询语句的orderBY条件和查询的执行计划中所利用的Index的索引键(或前面几个索引键)完全一致,且索引访问方式为rang,ref或者index的时候,MySQL可以利用索引顺序而直接取得已经排好序的数据。这种方式的orderBY基本上可以说是最优的排序方式了,因为MySQL不需要进行实际的排序操作。需要注意的是使用索引排序也有很多限制。这个在后文中中解释。

  2.利用内存/磁盘文件排序获取结果

  由于没有可以利用的有序索引取得有序的数据,MySQL需要通过相应的排序算法,将取得的数据在sort_buffer_size系统变量所设置大小的排序区进行排序,这个排序区是每个Thread独享的,所以说可能在同一时刻在MySQL中可能存在多个sortbuffer内存区域。

  在MySQL中filesort的实现算法有两种:

  1)双路排序:是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行指针信息,然后在sortbuffer中进行排序。

  2)单路排序:是一次性取出满足条件行的所有字段,然后在sortbuffer中进行排序。

  在MySQL4.1版本之前只有第一种排序算法,第二种算法是从MySQL4.1开始的改进算法,主要目的是为了减少第一次算法中需要两次访问表数据的IO操作,将两次变成了一次,但相应也会耗用更多的sortbuffer空间。典型的以空间换时间的优化方式。当然,MySQL4.1开始的以后所有版本同时也支持第一种算法,MySQL主要通过比较系统参数max_length_for_sort_data的大小和Query语句所取出的字段类型大小总和来判定需要使用哪一种排序算法。如果max_length_for_sort_data更大,则使用第二种优化后的算法,反之使用第一种算法。所以如果希望orderBY操作的效率尽可能的高,需要注意max_length_for_sort_data参数的设置。

  二、优化order by

  当无法避免排序操作时,又该如何来优化呢?很显然,优先选择第一种usingindex的排序方式,在第一种方式无法满足的情况下,尽可能让MySQL选择使用第二种单路算法来进行排序。这样可以减少大量的随机IO操作,很大幅度地提高排序工作的效率。

  1.加大max_length_for_sort_data参数的设置

  在MySQL中,决定使用老式排序算法还是改进版排序算法是通过参数max_length_for_sort_data来决定的。当所有返回字段的最大长度小于这个参数值时,MySQL就会选择改进后的排序算法,反之,则选择老式的算法。所以,如果有充足的内存让MySQL存放须要返回的非排序字段,就可以加大这个参数的值来让MySQL选择使用改进版的排序算法。

  2.去掉不必要的返回字段

  当内存不是很充裕时,不能简单地通过强行加大上面的参数来强迫MySQL去使用改进版的排序算法,否则可能会造成MySQL不得不将数据分成很多段,然后进行排序,这样可能会得不偿失。此时就须要去掉不必要的返回字段,让返回结果长度适应max_length_for_sort_data参数的限制。

  3.增大sort_buffer_size参数设置

  这个值如果过小的话,再加上你一次返回的条数过多,那么很可能就会分很多次进行排序,然后最后将每次的排序结果再串联起来,这样就会更慢,增大sort_buffer_size并不是为了让MySQL选择改进版的排序算法,而是为了让MySQL尽量减少在排序过程中对须要排序的数据进行分段,因为分段会造成MySQL不得不使用临时表来进行交换排序。

  但是这个值不是越大越好:

  1.Sort_Buffer_Size是一个connection级参数,在每个connection第一次需要使用这个buffer的时候,一次性分配设置的内存。

  2.Sort_Buffer_Size并不是越大越好,由于是connection级的参数,过大的设置+高并发可能会耗尽系统内存资源。

  3.据说Sort_Buffer_Size超过2M的时候,就会使用mmap()而不是malloc()来进行内存分配,导致效率降低。

  在某些情况中,MySQL可以使用一个索引来满足ORDERBY子句,而不需要额外的排序。where条件和orderby使用相同的索引,并且orderby的顺序和索引顺序相同,并且orderby的字段都是升序或者都是降序。

  例如:下列sql可以使用索引。

  SELECT*FROMt1ORDERBYkey_part1,key_part2,...;

  SELECT*FROMt1WHEREkey_part1=1ORDERBYkey_part1DESC,key_part2DESC;

  SELECT*FROMt1ORDERBYkey_part1DESC,key_part2DESC;

  但是以下情况不使用索引。

  1)SELECT*FROMt1ORDERBYkey_part1DESC,key_part2ASC;

  --orderby的字段混合ASC和DESC

  2)SELECT*FROMt1WHEREkey2=constantORDERBYkey1;

  --用于查询行的关键字与ORDERBY中所使用的不相同

  3)SELECT*FROMt1ORDERBYkey1,key2;

  --对不同的关键字使用ORDERBY

  小编结语:

  更多内容尽在课课家教育!

赞(20)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程