前言

排序是数据库中的一个基本功能,MySQL也不例外。通过Order by语句即能达到将指定的结果集排序的目的,

其实不仅仅是Order by语句,Group by语句,Distinct语句都会隐含使用排序

在实际业务场景中,一些开发的大牛动不动来个orderby,SQL看起写的非常溜,而实际业务应用导致GAME OVER......

首先介绍MySQL实现排序的内部原理,并介绍与排序相关的参数,最后结合实际给出几个"奇怪"排序,来谈谈排序一致问题

1、排序实现的算法:

对于不能利用索引避免排序的 SQL,数据库不得不自己排序功能以满足业务需求,执行计划中会出现"USING TEMPORARY; USING filesort",

有时候filesore并不意味着就是文件排序也有可能是内存排序,只有由参数sort_buffer_size和结果集大小确定。

MySQL内部排序主要有3种方式:常规排序、优化排序和优先队列排序,假设表结构如下:

CREATE TABLE `t1` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`col1` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,

`col2` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,

`col3` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `col1` (`col1`,`col2`)

) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

SELECT col1,col2,col3 FROM t1 WHERE col1="100" ORDER BY col2;

    a.常规排序

(1).从表t1中获取满足WHERE条件的记录

(2).对于每条记录,将记录的主键+排序键(id,col2)取出放入sort buffer

(3).如果sort buffer可以存放所有满足条件的(id,col2)对,则进行排序;否则sort buffer满后,进行排序并固化到临时文件中。(排序算法采用的是快速排序算法)

(4).若排序中产生了临时文件,需要利用归并排序算法,保证临时文件中记录是有序的

(5).循环执行上述过程,直到所有满足条件的记录全部参与排序

(6).扫描排好序的(id,col2)对,并利用id去捞取SELECT需要返回的列(col1,col2,col3)

(7).将获取的结果集返回

从上述流程来看,是否使用文件排序主要看sort buffer是否能容下需要排序的(id,col2)对,这个buffer的大小由sort_buffer_size参数控制。此外一次排序需要两次IO,一次是捞(id,col2),第二次是捞(col1,col2,col3),由于返回的结果集是按col2排序,因此id是乱序的,通过乱序的id去捞(col1,col2,col3)时会产生大量的随机IO。对于第二次MySQL本身一个优化,

即在捞之前首先将id排序,并放入缓冲区,这个缓存区大小由参数read_rnd_buffer_size控制,然后有序去捞记录,将随机IO转为顺序IO

b.优化排序

常规排序方式除了排序本身,还需要额外两次IO。优化的排序方式相对于常规排序,减少了第二次IO。主要区别在于,放入sort buffer不是(id,col2),而是(col1,col2,col3)。由于sort buffer中包含了查询需要的所有字段,因此排序完成后可以直接返回,无需二次捞数据。这种方式的代价在于,同样大小的sort buffer,能存放的(col1,col2,col3)数目要小于(id,col2),如果sort buffer不够大,可能导致需要写临时文件,造成额外的IO。当然MySQL提供了参数max_length_for_sort_data,

只有当排序元组小于max_length_for_sort_data时,才能利用优化排序方式,否则只能用常规排序方式

    c.优先队列排序

为了得到最终的排序结果,无论怎样,我们都需要将所有满足条件的记录进行排序才能返回。那么相对于优化排序方式,

在空间层面做了优化黑盒加入了一种新的排序方式--优先队列,这种方式采用堆排序实现,堆排序算法特征正好可以解limit M,N 这类排序的问题,虽然仍然需要所有元素参与排序,但是只需要M+N个元组的sort buffer空间即可,对于M,N很小的场景,基本不会因为sort buffer不够而导致需要临时文件进行归并排序的问题。

对于升序,采用大顶堆,最终堆中的元素组成了最小的N个元素,对于降序,采用小顶堆,最终堆中的元素组成了最大的N的元素

2、排序优化与索引使用

为了优化SQL语句的排序性能,最好的情况是避免排序,合理利用索引是一个不错的方法。

因为索引本身也是有序的,如果在需要排序的字段上面建立了合适的索引,那么就可以跳过排序的过程,提高SQL的查询速度,\

通过一些典型SQL说明哪些可以利用索引减少排序,哪些不能,

1、select * from t1 order by col1,col2

2、select * from t1 where  col1="100" order by col2

3、select *from t1 col1>"100" order by col1 asc

4、select * from  t1 where col1="100" and col2>"100" order by col2

3、不能利用索引避免排序

通过索引扫描的记录数超过30%,变全表扫描

联合索引中,第一索引列使用范围查询

联合索引中,第一查询条件不是最左索引列

升降序不一致无法使用

排序字段在多个索引中无法使用(一个联合索引一个单列索引,一条SQL一次只能使用一个索引)

排序字段是单独的列无法使用索引

4、业务案例,添加合理的索引

    1、业务DDL:

    

2、对原SQL执行计划的查看:

3、优化后的SQL执行计划-1

3、优化后的SQL执行计划-2

主要对原SQL进行改写以及添加相应的索引,即可实现SQL优化,运行效率的最优。

转载于:https://blog.51cto.com/dbaspace/1983590

ORDER BY分类相关推荐

  1. MySQL中实现Oracle里面 rank()over ( PARTITION BY ORDER BY) 分类分组功能

    各班级学生成绩测试表 select * from TMP_A; 实现目的: 按照班级分类后按照分数倒序排序 采用MySQL变量简单实现,SQL如下: SELECT  a.stu_id,a.point, ...

  2. Oracle基础语句

    1.创建表 create table IT_EMPLOYEES ( ENPLOYEES_ID NUMBER(6) NOT NULL UNIQUE, FIRST_NAME VARCHAR2(20), L ...

  3. php项目怎么分配,php项目目录的合理划分和Pipeline 组件的使用场景

    php项目目录的合理划分和Pipeline 组件的使用场景 这是一篇迟到的文章,很早之前就一直想写了,可是经验不足有些地方理解的不透侧,当然,现在这篇文章可能也是浅尝辄止,希望不要喷我 开篇 首先,可 ...

  4. 13 MATLAB判别分析

    更多MATLAB数据分析视频请点击,或者在网易云课堂上搜索<MATLAB数据分析与统计> http://study.163.com/course/courseMain.htm?course ...

  5. SQL Server习题及答案3

    SQL Server题库 一 选择题 2.下列哪个标识符不是SQL SERVER 2005的常规标识符(A ). A.3b B.#xuesheng C.##xuesheng D.2abc 3.下列哪个 ...

  6. MySQL精讲(一) |DQL数据查询语句全解析

    MySQL精讲系列文章(更新完毕) <MySQL入门必看知识> <MySQL精讲(一) | DQL数据查询语句全解析> <MySQL精讲(二) | DML数据操作语句全解 ...

  7. MySQL入门代码(附案例)

    Mysql入门学习笔记,包含简单查询.常用函数.分组查询.多表查询.(嵌套)子查询.分页查询.联合查询.表中数据的增删改(DML).表和库的增删改(DDL).数据类型.常见约束.标识列.事务(TCL) ...

  8. 使用uni-app搭建微信小程序

    0 问题待解决 import { } 与否 为什么要封装 对齐问题 每次重启项目,sitemap就会消失 动态修改标题失效 图片问题多多 :高度自适应 改成image固定高度,mode:aspectF ...

  9. PBDB Data Service:Measurements of specimens(标本测量)

    Measurements of specimens(标本测量) 描述 参数 以下参数可用于指定您感兴趣的标本种类 以下参数可用于筛选所选内容 以下参数还可用于根据分类筛选结果列表 以下参数可用于生成数 ...

最新文章

  1. 网站关键词如何布局更有利于关键词排名提升?
  2. 如何恢复默认域策略和默认域控制器策略
  3. 神经网络推理_分析神经网络推理性能的新工具
  4. 实操案例丨如何实现特定列脱敏
  5. Cocos2d-x Touch事件处理机制(better)
  6. edui 富文本编辑_百度umeditor富文本编辑器插件扩展
  7. 【算法笔记】马拉车算法:最长回文子串
  8. 【DL学习笔记06】深度学习入门——基于Python的理论与实现(ch07: 卷积神经网络 CNN)
  9. windows cmd 批处理将文件名改为大写:https://blog.csdn.net/llq108/article/details/47185279
  10. 三十功名尘与土,八千里路云和月
  11. 【ZYNQ】从入门到秃头01 初识ZYNQ(PS和PL之间连接)
  12. 2021年茶艺师(初级)考试及茶艺师(初级)考试总结
  13. python redis连接_Python连接Redis连接配置
  14. 【应用随机过程】03. 马尔可夫链的状态
  15. 新站的几种简单的推广方法
  16. 计算机视觉实习生面试经验(微软/腾讯(AI Lab优图)/阿里巴巴)
  17. 3CLpro-抗新冠病毒药物研究首选靶点
  18. 爬取最好大学网排名数据
  19. .net WebApi中使用swagger
  20. leetcode142之寻找环形链表的环的起点

热门文章

  1. c语言gets,getc,C语言的getc()函数和gets()函数的使用对比
  2. 计算机专业中英文,计算机专业词汇中英文对照
  3. springboot 循环引用问题
  4. java异常机制_全面理解java异常机制
  5. curl 慢 不稳定_徐工起重机:龟速一样"慢"的机器,竟还有人抢着买?
  6. linux安装java路径_Linux环境中查看java的安装路径,设置环境变量
  7. mq 2085 java_websphere mq 不能访问集群中其它节点对列
  8. JAVA 中 Redis与ehcache对比与使用
  9. java中如何播放背景mp3音乐_java播放背景音乐
  10. 机器学习_一条会说666的咸鱼