0

0

mysql中的order by_MySQL

php中文网

php中文网

发布时间:2016-05-30 17:10:52

|

3052人浏览过

|

来源于php中文网

原创

一、order by的原理

 

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

 

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

 

当对连接操作进行排序时,如果ORDER BY仅仅引用第一个表的列,MySQL对该表进行filesort操作,然后进行连接处理,此时,EXPLAIN输出“Using filesort”;否则,MySQL必须将查询的结果集生成一个临时表,在连接完成之后进行filesort操作,此时,EXPLAIN输出“Using temporary;Using filesort”。

 

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

 

mysql> show create table test \G
*************************** 1. row ***************************
       Table: test
Create Table: CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `addtime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `a` int(11) unsigned NOT NULL,
  `b` int(11) unsigned NOT NULL,
  `c` int(11) unsigned NOT NULL,
  `data` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `u` (`addtime`,`a`,`b`),
  KEY `a` (`a`),
  KEY `b` (`b`),
  KEY `c` (`c`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8

 

执行查询1

 

mysql> explain  select * from test where addtime='2015-10-13 15:38:32' order by  a , b ;

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

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

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

|  1 | SIMPLE      | test  | ref  | u             | u    | 8       | const |    4 | Using where |

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

  执行查询2

 

mysql> explain  select * from test where addtime='2015-10-13 15:38:32' order by  a , b ,c;

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

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

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

|  1 | SIMPLE      | test  | ref  | u             | u    | 8       | const |    4 | Using where; Using filesort |

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

使用filesort的情况

 

a、where语句与order by语句,使用了不同的索引

 

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

 

c、对索引列同时使用了ASC和DESC

 

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

 

e、where 语句与ORDER BY语句组合满足最左前缀,但where语句中使用了条件查询

 

f、 当使用left join,使用右边的表字段排序

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

 

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

 

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

 

1) 双路排序: 是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行指针信息,然后在sort buffer 中进行排序(but this will be essentially hit the table in random order and is not very fast)。

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

 

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

 

MySQL主要通过比较系统参数 max_length_for_sort_data的大小和Query语句所取出的字段类型大小总和来判定需要使用哪一种排序算法。如果max_length_for_sort_data更大,则使用第二种优化后的算法,反之使用第一种算法。所以如果希望 order BY 操作的效率尽可能的高,需要注意max_length_for_sort_data参数的设置。

 

3、使用Using temporary 临时表来filesort

 

如果order by的子句只引用了联接中的第一个表,MySQL会先对第一个表进行排序,然后进行联接,expain中的Extra会出现Using Filesort

 

否则MySQL先把结果保存到临时表(Temporary Table),然后再对临时表的数据进行排序,此时expain中的Extra的显示Using temporary Using Filesort

 

4、Join排序

 

mysql中有三种方式

PHP简约自动发卡平台个人版
PHP简约自动发卡平台个人版

PHP自动发卡平台个人版是采用php+mysql进行开发的自动发卡支付平台。服务器环境:PHP5.2以上版本mysql5.1 或以上版本安装说明:安装 http://你的域名/install.php 进行安装,后台路径http://你的域名/admin 后台账号:admin 后台密码:yc88.net需要修改用户名,可以进入数据库进行修改faka_users把admin改成其他支持改成中文

下载

 

1)、Use index-based access method that produces ordered output  -》 null

 

mysql中的order by_MySQL

 

2)、Use filesort() on 1st non-constant table -》 “Using filesort” in the first row

 

mysql中的order by_MySQL

 

3)、Put join result into a temporary table and use filesort() on it   -》  “Using temporary; Using filesort” in the first row

 

mysql中的order by_MySQL

5、说一下filesort,可以参考 What does Using filesort mean in MySQL?

 

摘自原文

 

 

 

The truth is, filesort is badly named. Anytime a sort can’t be performed from an index, it’s a filesort. It has nothing to do with files. Filesort should be called “sort.” It is quicksort at heart.

 

 

 

If the sort is bigger than the sort buffer, it is performed a bit at a time, and then the chunks are merge-sorted to produce the final sorted output. There is a lot more to it than this. I refer you to Sergey Petrunia’s article on How MySQL executes ORDER BY. You can also read about it in our book, but if you read Sergey’s article you won’t need to.

 

 

 

这里有一个误区,容易望文生义,Explain 命令输出信息中的 filesort 到底是什么意思呢?其实很简单,就是告诉你 MySQL 需要进行实际的排序操作而不能通过索引获得已排序数据

 

 

 

1)、filesort(其实就是排序) 可不一定会产生临时表

 

2)、filesort 与临时表数据写入磁盘是没有任何直接联系的

 

 

二 、优化order by

 

当无法避免排序操作时,又该如何来优化呢?很显然,优先选择第一种using index 的排序方式,在第一种方式无法满足的情况下,尽可能让 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() 来进行内存分配,导致效率降低。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 生态工具与框架:扩展开发能力
Golang 生态工具与框架:扩展开发能力

《Golang 生态工具与框架》系统梳理 Go 语言在实际工程中的主流工具链与框架选型思路,涵盖 Web 框架、RPC 通信、依赖管理、测试工具、代码生成与项目结构设计等内容。通过真实项目场景解析不同工具的适用边界与组合方式,帮助开发者构建高效、可维护的 Go 工程体系,并提升团队协作与交付效率。

1

2026.02.24

Golang 性能优化专题:提升应用效率
Golang 性能优化专题:提升应用效率

《Golang 性能优化专题》聚焦 Go 应用在高并发与大规模服务中的性能问题,从 profiling、内存分配、Goroutine 调度、GC 机制到 I/O 与锁竞争逐层分析。结合真实案例讲解定位瓶颈的方法与优化策略,帮助开发者建立系统化性能调优思维,在保证代码可维护性的同时显著提升服务吞吐与稳定性。

2

2026.02.24

Golang 面试题精选:高频问题与解答
Golang 面试题精选:高频问题与解答

Golang 面试题精选》系统整理企业常见 Go 技术面试问题,覆盖语言基础、并发模型、内存与调度机制、网络编程、工程实践与性能优化等核心知识点。每道题不仅给出答案,还拆解背后的设计原理与考察思路,帮助读者建立完整知识结构,在面试与实际开发中都能更从容应对复杂问题。

1

2026.02.24

Golang 运行与部署实战:从本地到云端
Golang 运行与部署实战:从本地到云端

《Golang 运行与部署实战》围绕 Go 应用从开发完成到稳定上线的完整流程展开,系统讲解编译构建、环境配置、日志与配置管理、容器化部署以及常见运维问题处理。结合真实项目场景,拆解自动化构建与持续部署思路,帮助开发者建立可靠的发布流程,提升服务稳定性与可维护性。

3

2026.02.24

Golang 疑难杂症解决指南:常见问题排查与优化
Golang 疑难杂症解决指南:常见问题排查与优化

《Golang 疑难杂症解决指南》聚焦开发过程中常见却棘手的问题,从并发模型、内存管理、性能瓶颈到工程化实践逐步拆解。通过真实案例与调试思路,帮助开发者定位问题根因,建立系统化排查方法。不只给出答案,更强调分析路径与工具使用,让你在复杂 Go 项目中具备持续解决问题的能力。

1

2026.02.24

Golang 入门学习路线:从零基础到上手开发
Golang 入门学习路线:从零基础到上手开发

Golang 入门路线涵盖从零到上手的核心路径:首先打牢基础语法与切片等底层机制;随后攻克 Go 的灵魂——接口设计与 Goroutine 并发模型;接着通过 Gin 框架与 GORM 深入 Web 开发实战;最后在微服务与云原生工具开发中进阶,旨在培养具备高性能并发处理能力的后端工程师。

0

2026.02.24

中国研究生招生信息网官方网站入口 研招网网页版在线入口
中国研究生招生信息网官方网站入口 研招网网页版在线入口

中国研究生招生信息网入口(https://yz.chsi.com.cn) 此网站是研究生报名入口的唯一官方网站

95

2026.02.24

苹果官网入口与在线访问指南_中国站点快速直达与iPhone查看方法
苹果官网入口与在线访问指南_中国站点快速直达与iPhone查看方法

本专题汇总苹果官网最新可用入口及中国站点访问方式,涵盖官网直达链接、iPhone官方页面查看方法与常见访问说明,帮助用户快速进入苹果官方网站,便捷了解产品信息与官方服务。

14

2026.02.24

Asianfanfics官网入口与访问指南_AFF官方平台最新登录地址
Asianfanfics官网入口与访问指南_AFF官方平台最新登录地址

本专题系统整理Asianfanfics(AFF)官方网站最新可用入口,涵盖官方平台最新直达地址、官网登录方式及中文访问指引,帮助用户快速、安全地进入AFF平台浏览与使用相关内容。

15

2026.02.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2.4万人学习

Kotlin 教程
Kotlin 教程

共23课时 | 3.9万人学习

MongoDB 教程
MongoDB 教程

共17课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号