在MySQL中的ORDER BY有两种排序实现方式:

1、利用有序索引获取有序数据

2、文件排序

在使用explain分析查询的时候利用有序索引获取有序数据显示Using index。而文件排序显示Using filesort。


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

取出满足过滤条件作为排序条件的字段,以及可以直接定位到行数据的行指针信息,在 Sort Buffer 中进行实际的排序操作,然后利用排好序的数据根据行指针信息返回表中取得客户端请求的其他字段的数据,再返回给客户端.

         注意:mysql在查询时最多只能使用一个索引。因此,如果WHERE条件已经占用了索引,那么在排序中就不使用索引了。


按照索引对结果进行排序:order by 使用索引是有条件:

1)  返回选择的字段,即只包括在有选择的此列上(select后面的字段),不一定适应*的情况):

  1. CREATE TABLE `test` (
  2. `id` int(11) NOT NULLAUTO_INCREMENT,
  3. `rdate` datetime NOT NULL,
  4. `inventid` int(11) NOT NULL,
  5. `customerid` int(11) NOT NULL,
  6. `staffid` int(11) NOT NULL,
  7. `data` varchar(20) NOT NULL,
  8. PRIMARY KEY (`id`),
  9. UNIQUE KEY `rdate`(`rdate`,`inventid`,`customerid`),
  10. KEY `inventid` (`inventid`),
  11. KEY `customerid` (`customerid`),
  12. KEY `staffid` (`staffid`)
  13. ) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=latin1

如:

  1. mysql>
  2. explain select inventid from test where rdate='2011-12-1400:00:00' order by  inventid , customerid;

+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+

| id | select_type | table | type | possible_keys |key    | key_len |ref      | rows |Extra                    |

+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+

|  1 |  SIMPLE      | test    |ref   |        rdate          |rdate  |      8     |const |   10   | Using where; Using index |

+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+

1 row in set (0.00 sec)

Select选择的列使用索引,而下面不使用索引:

mysql> explain select * from test where rdate='2011-12-14 00:00:00'order by  inventid , customerid ;

+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+

| id | select_type | table | type | possible_keys | key     | key_len|ref     | rows | Extra                       |

+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+

|  1 | SIMPLE      | test   | ALL  | rdate               | NULL  | NULL    |NULL |  13   |Using where;Using filesort|

+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+

2)  只有当ORDER BY中所有的列必须包含在相同的索引,并且索引的顺序和order by子句中的顺序完全一致,并且所有列的排序方向(升序或者降序)一样才有,(混合使用ASC模式和DESC模式则不使用索引)

  1. mysql>
  2. xplain select inventid from test order byrdate, inventid ;

+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra       |

+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

|  1 | SIMPLE      | test  | index | NULL          | rdate |16      | NULL |   13 |Using index|

+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

1 row in set (0.00 sec)

  1. mysql>
  2. explain select inventid from test where rdate="2011-12-16" order by  inventid ,staffid;

+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------

| id | select_type | table | type | possible_keys |key   | key_len | ref   | rows | Extra                       |

+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------

|  1 | SIMPLE      | test | ref  | rdate         | rdate | 8       | const |    1 |Using where;Using filesort

+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------

1 row in set (0.00 sec)

由于rdate, inventid使用了同一个索引。排序使用到了索引。这个也是满足了前缀索引。但是order  by  inventid ,staffid;就不是使用了索引,因为staffid和inventid不是同一个索引

3)     where 语句与ORDER BY语句组合满足最左前缀:

  1. mysql>
  2. explain select inventid from test whererdate="2011-12-16" order by  inventid ;

+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+

| id | select_type | table | type | possible_keys | key   | key_len | ref   | rows | Extra                    |

+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+

|  1 | SIMPLE      | test | ref  | rdate         | rdate | 8       | const |    1 | Using where;Using index |

+----+-------------+-------+------+---------------+-------+---------+-------+------+--------------------------+

1 row in set (0.00 sec)

4)     如果查询联接了多个表,只有在order by子句的所有列引用的是第一个表的列才可以。


5)     在其他的情况下,mysql使用文件排序   例如:

1)   where语句与order by语句,使用了不同的索引

2)   where语句和order by同时使用1个索引,此时where已经做好排序了,order by将不会使用index排序也不会使用文件排序

3)   检查的行数过多,且没有使用覆盖索引

4)   ORDER BY中的列不包含在相同的索引,也就是使用了不同的索引

5)   对索引列同时使用了ASC和DESC

6)   where语句或者ORDER BY语句中索引列使用了表达式,包括函数表达式

7)   where 语句与ORDER BY语句组合满足最左前缀,但where语句中使用了条件查询。查见第10句,虽然where与order by构成了索引最左有缀的条件,但是where子句中使用的是条件查询

mysql> explain select inventid from test where  rdate>"2011-12-16" order by  inventid;

+----+-------------+-------+-------+---------------+-------+---------+------+------+----------------

| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra

+----+-------------+-------+-------+---------------+-------+---------+------+------+----------------

|  1 |SIMPLE      | test  | range | rdate         | rdate | 8       | NULL |    1 | Using where; Using index;Usingfilesort |

+----+-------------+-------+-------+---------------+-------+---------+------+------+----------------

1 row in set (0.00sec)

        8)   当使用left join,使用右边的表字段排序

2.文件排序

这个 filesort 并不是说通过磁盘文件进行排序,而只是告诉我们进行了一个排序操作。即在MySQL Query Optimizer 所给出的执行计划(通过 EXPLAIN 命令查看)中被称为文件排序(filesort)

文件排序是通过相应的排序算法,将取得的数据在内存中进行排序: MySQL需要将数据在内存中进行排序,所使用的内存区域也就是我们通过sort_buffer_size 系统变量所设置的排序区。这个排序区是每个Thread 独享的,所以说可能在同一时刻在MySQL 中可能存在多个 sort buffer 内存区域。

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

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

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

在MySQL4.1版本之前只有第一种排序算法双路排序,第二种算法是从MySQL4.1开始的改进算法,主要目的是为了减少第一次算法中需要两次访问表数据的 IO 操作,将两次变成了一次,但相应也会耗用更多的sortbuffer 空间。当然,MySQL4.1开始的以后所有版本同时也支持第一种算法,

MySQL主要通过比较我们所设定的系统参数 max_length_for_sort_data的大小和Query 语句所取出的字段类型大小总和来判定需要使用哪一种排序算法。如果 max_length_for_sort_data更大,则使用第二种优化后的算法,反之使用第一种算法。所以如果希望 ORDER BY 操作的效率尽可能的高,一定要主义max_length_for_sort_data 参数的设置。曾经就有同事的数据库出现大量的排序等待,造成系统负载很高,而且响应时间变得很长,最后查出正是因为MySQL 使用了传统的第一种排序算法而导致,在加大了max_length_for_sort_data 参数值之后,系统负载马上得到了大的缓解,响应也快了很多。

Order By文件排序和索引排序相关推荐

  1. Pandas数据排序——【按索引排序sort_index()方法、按值排序sort_value()方法】

    文章目录 按索引排序--sort_index() 对Series排序 对DataFrame排序 按值排序--sort_value() 对Series进行排序 对DataFrame进行排序 按索引排序- ...

  2. 为排序使用索引OrderBy优化

    order by关键字优化 1. ORDER BY子句,尽量使用Index方式排序,避免使用FileSort方式排序 建表SQL CREATE TABLE tblA(#id int primary k ...

  3. 查询排序_Mysql在排序和查询时不使用索引的情况

    1. 写在前头 这篇文章<Mysql是怎样运行的>,参考书中P123 - P125,它列举的就是在排序时不使用索引的情况,这让我回想起在面试的时候,被问到在查询时不使用索引的情况,所以我想 ...

  4. MySql 你知道 order by 是怎么回事吗? MySql全字段排序与 rowid 排序

    志在巅峰的攀登者,不会陶醉在沿途的某个脚印之中,在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天.每周,都会留下一些脚印,就是这些创作的 ...

  5. mysql 排序字段索引吗_Mysql 排序优化与索引使用(转)

    为了优化SQL语句的排序性能,最好的情况是避免排序,合理利用索引是一个不错的方法.因为索引本身也是有序的,如果在需要排序的字段上面建立了合适的索引,那么就可以跳过排序的过程,提高SQL的查询速度.下面 ...

  6. mysql索引排序算法_MySQL中利用索引对数据进行排序的基础教程

    MySQL中,有两种方式生成有序结果集:一是使用filesort,二是按索引顺序扫描.利用索引进行排序操作是非常快的,而且可以利用同一索引同时进行查找和排序操作.当索引的顺序与ORDER BY中的列顺 ...

  7. python numpy np.argsort()(返回将对数组进行排序的索引)(不懂区别?)

    from numpy\core\fromnumeric.py @array_function_dispatch(_argsort_dispatcher) def argsort(a, axis=-1, ...

  8. java 索引排序_Java培训MySQL之排序分组优化索引的选择

    索引的选择 ①首先,清除emp上面的所有索引,只保留主键索引! drop index idx_age_deptid_name on emp; ②查询:年龄为30岁的,且员工编号小于101000的用户, ...

  9. 《MySQL——order by逻辑(全字段排序与rowid排序)》

    创建一个表,然后使用查询语句: 查询城市是"杭州"的所有人名字,并且按照姓名排序返回前 1000 个人的姓名.年龄 create table 't' ('id' int(11) n ...

最新文章

  1. 不能打游戏的汽车不是好电影院!特斯拉面向国内推送V10.0系统,能辅助变道还能看爱奇艺...
  2. c语言怎么解析midi文件,c – 无法读取midi文件? [扩展规格?]
  3. 笔记-项目合同管理-索赔的处理
  4. C++primer第二章2.4节对于const限定符相关内容进行详解
  5. table超出边框出现滚动条_精美横轴智能滚动条设计
  6. SharePoint 2013 版本功能对比
  7. (转)Uncaught TypeError: Cannot set property 'innerHTML' of null
  8. Windows 7如何无线上网和宽带上网
  9. js如何准确获取当前页面url网址信息
  10. 【学习】从零开始的Android音视频开发(6)——MediaPlayerService中BinderDriver、创建播放器过程、建立StageFright层交互
  11. 聊聊大龄程序员的一条出路
  12. 用MFC实现WebGUI--(CDHtmlDialog)
  13. GBase 8c数据库登陆
  14. 列出叶节点 python
  15. 28岁自学Python转行靠谱吗?入行晚吗?
  16. 2018传智黑马前端视频教程
  17. 互联网日报 | 蔚来汽车股价年内涨幅近十倍;小米成立可穿戴部;恒大物业拟12月2日港交所上市...
  18. Qt学习:QtCharts绘制动态曲线,实时更新数据与坐标轴
  19. 恶劣天气中如何拍摄360全景图片?
  20. Jvm-Sandbox-Repeater的部署

热门文章

  1. Collection 和 List
  2. Canny算子Matlab实现
  3. C语言 输入字符 ,判断是否为字母(包括大小写)
  4. JQuery 学习总结
  5. karen 软件测试_使用Karen的复制器轻松备份数据
  6. opencv打开手机网络摄像头
  7. 第八篇:qt写ui转py文件之pyside2转py(全步骤)
  8. lower_bound( )和upper_bound( )的返回值及用法
  9. Java---GUI编程详解
  10. query string 查询