MySQL中的两种排序方式

  1. .通过有序索引顺序扫描直接返回有序数据
    因为索引的结构是B+树,索引中的数据是按照一定顺序进行排列的,所以在排序查询中如果能利用索引,就能避免额外的排序操作。EXPLAIN分析查询时,Extra显示为Using index。MySQL会结合SQL中的where、order by中的字段去选择索引。
  2. .Filesort排序即对返回的数据进行排序
    所有不是通过索引直接返回排序结果的操作都是Filesort排序,也就是说进行了额外的排序操作。EXPLAIN分析查询时,Extra显示为Using filesort。

无法使用索引排序的情况

首先要注意:

MySQL一次查询只能使用一个索引,如果要对多个字段使用索引,建立复合索引。

注:下列key指代索引,key_part1、key_part2…指代索引中的顺序字段

  1. 排序字段在不同的索引中,无法使用索引排序:
SELECT * FROM t1 ORDER BY key1_part1, key2_part1;
  1. 对关键字的非连续元素使用ORDER BY,order by 使用索引除了前导列为常量时可以不满足最左前缀原则,其他时候都需要满足最左前缀原则
//跳过了key_part1,不满足最左前缀不使用索引
SELECT * FROM t1 ORDER BY key_part2;//前导列为常量,此时可以不满足最左前缀,使用索引
SELECT * FROM t1 WHERE key_part1=常量 ORDER BY key_part2;
  1. 混合ASC和DESC:
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
  1. 用于查询行的索引与ORDER BY中所使用的索引不相同
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
  1. 有不同的ORDER BY和GROUP BY表达式。
SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2 group by key_part3;

通过B+Tree结构判断索引是否能用于排序

索引是B+Tree的结构,能否使用某个索引来避免排序可以通过数据在B+Tree中的是否有序判断,下文有具体例子。

InnoDB的聚簇索引结构如下:

由此可知道,聚簇索引可以用于主键的排序,即order by 主键。

InnoDB的二级索引结构如下:

(1)二级索引的叶节点并不包含行记录的全部数据,仅包含索引中的所有键和一个用于查找对应行记录的主键值。(非叶子节点不包含主键

(2)Innodb二级索引,索引列值全相同的情况下,节点按主键值排序。

(3)二级索引键值的顺序和聚簇索引键值顺序通常不同,所以二级索引做范围查询读取记录的性能通常不如聚簇索引高效查询的列不存在二级索引时需要回表,回表操作会有大量的随机IO)。

是否使用索引排序取决于使用索引的成本

在满足了使用索引排序的条件(上文提及不可用索引排序的情况)的前提下,是否使用索引、使用哪个索引取决于使用索引的成本

设有表 t(id, create_at),主键为id,同时有索引 index(create_at)。不同查询索引 index(create_at) 的使用情况:
(1)SELECT id FROM t WHERE create_at='2019年10月15日' ORDER BY idSELECT create_at FROM t WHERE create_at='2019年10月15日' ORDER BY id

等值查询,create_at='2019年10月15日'的节点在 索引 index(create_at)结构中按主键(id)的顺序存储,因此使用index(create_at)可以避免排序,同时因为覆盖了所有列,无需回表(Extra 出现 Using index)

(2)SELECT * FROM t WHERE create_at='2019年10月15日' ORDER BY id

等值查询,create_at='2019年10月15日'的节点在 索引 index(create_at)结构中按主键(id)的顺序存储,因此使用index(create_at)可以避免排序,虽然需要回表但是通过索引可以过滤大部分的数据,成本低于使用聚簇索引

(3)SELECT * FROM t WHERE create_at>'2019年10月15日' ORDER BY id

索引 index(create_at) 不包含所有数据,因此使用 index(create_at)做范围查询,每读取每条记录都需要回表查询,会有大量的随机IO,同时,此时在index(create_at)上id是无序的,所以性能不如直接使用聚簇索引。所以该查询使用主键,通过对主键的聚簇索引进行扫描,只需要过滤掉不满足条件的值而不需要排序

范围查询,需要回表,回表操作会有大量的随机IO
(4)SELECT create_at FROM t WHERE create_at>'2019年10月15日' ORDER BY id
SELECT id FROM t WHERE create_at>'2019年10月15日' ORDER BY id

此查询因为索引 index(create_at) 包含所需列,不需要回表查询,因此使用index(create_at) 可以扫描更少的行,成本低于使用主键索引。

参考

  • 推荐阅读:浅谈InnoDB中的聚簇索引和二级索引[译]
  • order by 原理以及优化
  • MySQL——优化ORDER BY语句
  • MySQL官网

Mysql优化(三):优化order by相关推荐

  1. 简易mysql优化_优化 MySQL:简单三个技巧

    原标题:优化 MySQL:简单三个技巧 技巧#1:为临时表分配足够的内存 在某些情况下,服务器在处理语句时会创建内部临时表.临时表用于内部操作如GROUP BY和distinct,还有一些ORDER ...

  2. 读薄《高性能MySql》(三)索引优化

    读薄<高性能MySql>(一)MySql基本知识 读薄<高性能MySql>(二)Scheme与数据优化 读薄<高性能MySql>(三)索引优化 读薄<高性能M ...

  3. MySQL各种优化基于《高性能MySQL第三版》

    [TOC] MySQL各种优化 查询优化 查询优化器模块 查询优化器的任务是发现执行 SQL 查询的最佳方案.大多数查询优化器,要么基于规则.要么基于成本. 大多数查询优化器,包含 MySQL 的查询 ...

  4. mysql悲观锁优化_MySQL数据库优化(三)—MySQL悲观锁和乐观锁(并发控制)

    一.悲观锁 1.排它锁,当事务在操作数据时把这部分数据进行锁定,直到操作完毕后再解锁,其他事务操作才可操作该部分数据.这将防止其他进程读取或修改表中的数据. 2.实现:大多数情况下依靠数据库的锁机制实 ...

  5. MySQL查询优化之十-ORDER BY优化(ORDER BY Optimization)

    MySQL查询优化之十-ORDER BY优化(ORDER BY Optimization) 如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:1295180 ...

  6. Python全栈(三)数据库优化之10.MySQL高级-表优化和索引优化

    文章目录 一.单表优化 二.双表优化 三.三表优化 四.索引优化 1.建表: 2.插入数据: 3.建立复合索引: 4.口诀: 全值匹配我最爱: 最左前缀要遵守: 带头大哥不能死: 中间兄弟不能断: 索 ...

  7. mysql+翻页性能,mysql 翻页优化

    mysql翻页优化 对于翻页,我们通常是用 select fields from table limit 100,10 但是当要越翻后面的页数之后,耗时变得很长 select fields from ...

  8. mysql sql优化_浅谈mysql中sql优化

    说到sql优化,一般有几个步骤呢,在网上看到了一篇很不错的帖子.在这分享一下吧,也是自己学习的一个过程. 一.查找慢查询 1.1.查看SQL执行频率 SHOW STATUS LIKE 'Com_%'; ...

  9. 淘宝内部分享:MySQL MariaDB性能优化

     淘宝内部分享:MySQL & MariaDB性能优化 摘要:MySQL是目前使用最多的开源数据库,但是MySQL数据库的默认设置性能非常的差,必须进行不断的优化,而优化是一个复杂的任务, ...

  10. mysql如何建立索引workbench_如何对MySQL索引进行优化分析

    为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字段的意义.助你了解索引, ...

最新文章

  1. access 打印预览 代码_PDFFactory pro虚拟打印机下载-PDFFactory官方版下载
  2. sudo spctl --master-disable_Φ560加长哈夫节--南宫哈夫节定做厂家
  3. 下拉菜单连动效果的一种用法
  4. Beginning SDL 2.0(4) YUV加载及渲染
  5. 笔记整理之 SHELL 变量
  6. mysql 日期操作 增减天数、时间转换、时间戳(转换)
  7. Unix/Linux下的open函数(O_CREAT和O_EXCL)
  8. Ubuntu16.04 下convert 命令 将eps转tif,jpg,png,pdf格式
  9. 新增本地存储功能 山石网科发布下一代防火墙新品
  10. java 多项式拟合最多的项数_Matlab polyfit 详解 | 方程组求解的稳定性 | 条件数
  11. vue-oss阿里云上传图片
  12. macbook linux 双系统,mac上安装ubuntu双系统教程
  13. Python爬虫 小白第一次爬虫
  14. 基于分类分级的医疗临床数据合规共享与安全防护建设实践
  15. Unite 2018 | 《崩坏3》:在Unity中实现高品质的卡通渲染(下)
  16. 浅谈RASP技术攻防之实战
  17. WORKNC基础到进阶视频教程
  18. JS验证身份证号码合法性
  19. jQuery实现ajax跨域请求
  20. 开源会是SD-WAN的发展方向吗?

热门文章

  1. BZOJ #3064. Tyvj 1518 CPU监控(线段树,历史最值)
  2. CF626F. Bear and Fair Set
  3. 斜率优化Convex Hull Trick
  4. [SDOI2019] 热闹的聚会与尴尬的聚会
  5. YbtOJ-染色计划【树链剖分,线段树,tarjan】
  6. P4258-[WC2016]挑战NPC【带花树】
  7. CF755G-PolandBall and Many Other Balls【倍增FFT】
  8. CF700E-Cool Slogans【SAM,线段树合并,dp】
  9. 牛客练习赛50-记录
  10. ssl初一组周六模拟赛【2018.4.7】