一:概述

  - order by 用于 SQL 语句中的排序。

  - 以  select city,name,age from t where city='杭州' order by name limit 1000 ; 举例,来了解下排序的工作原理。

  - 为了避免其他因素的影响,我们为 city 字段加上索引。

二:分析排序

  - 分析

    -  使用 explain 命令来看看这个语句的执行情况。

      - 

  - 可以看到,在 Extra 这个字段中的“Using filesort”表示的就是需要排序。

  - 在排序时候,MySQL 会给每个线程分配一块内存用于排序,称为 sort_buffer。

二:全字段排序(排序字段未使用索引)

  - 什么时候使用全字段排序?

    - 字段较少,数据量较小,排序可在内存中完成,Mysql 的大部分不走索引的排序都是使用 全字段排序完成的。

 

  - 全字段索引排序流程

    - 初始化 sort_buffer,确定放入 name、city、age 这三个字段。

    - 从索引 city 找到第一个满足 city='杭州’条件的主键 id。

    - 到主键 id 索引取出整行,取 name、city、age 三个字段的值,存入 sort_buffer 中;

    - 从索引 city 取下一个记录的主键 id;

    - 重复步骤 3、4 直到 city 的值不满足查询条件为止。

    - 对 sort_buffer 中的数据按照字段 name 做快速排序;

    - 按照排序结果取前 1000 行返回给客户端。

  - 流程细节

    - 整个的排序动作,可能在内存中完成,也可能需要使用外部排序,这取决于排序所需的内存和参数 sort_buffer_size。

    - sort_buffer_size,就是 MySQL 为排序开辟的内存(sort_buffer)的大小。

      - 如果要排序的数据量小于 sort_buffer_size,排序就在内存中完成。

      - 但如果排序数据量太大,内存放不下,则不得不利用磁盘临时文件辅助排序。外部排序一般使用归并排序算法。

三: rowid 排序(排序字段未使用索引)

  - 什么时候使用 rowid 排序?

    - 在 全字段排序 中,只对原表的数据读了一遍,剩下的操作都是在 sort_buffer 和临时文件中执行的。

    - 但是存在一个问题,如果查询要返回的字段很多,sort_buffer 放的字段数太多,这样内存里能够同时放下的行数很少,要分成很多个临时文件,排序的性能会很差。

    - Mysql 认为 全字段排序代价太大,于是使用 rowid 算法排序。

  - rowid 排序流程

    - 初始化 sort_buffer,确定放入两个字段,即 name 和 id。

    - 从索引 city 找到第一个满足 city='杭州’条件的主键 id。

    - 到主键 id 索引取出整行,取 name、id 这两个字段,存入 sort_buffer 中。

    - 从索引 city 取下一个记录的主键 id。

    - 重复步骤 3、4 直到不满足 city='杭州’条件为止。

    - 对 sort_buffer 中的数据按照字段 name 进行排序。

    - 遍历排序结果,取前 1000 行,并按照 id 的值回到原表中取出 city、name 和 age 三个字段返回给客户端。

  - 流程细节

    -  对比 全字段排序流程你会发现,rowid 排序多访问了一次表 的主键索引

四: 全字段排序 对比 rowid 排序?

  - 如果 MySQL 实在是担心排序内存太小,会影响排序效率,才会采用 rowid 排序算法,这样排序过程中一次可以排序更多行,但是需要再回到原表去取数据。

  - 对于 InnoDB 表来说,rowid 排序会要求回表多造成磁盘读,因此不会被优先选择。

五:索引排序(排序字段使用索引)

  - 新建立排序字段索引

    - 还是上面的 SQL 查询, 这里建立 city,name 的联合索引。

  - 再看索引排序流程

    - 从索引 (city,name) 找到第一个满足 city='杭州’条件的主键 id。

    - 到主键 id 索引取出整行,取 name、city、age 三个字段的值,作为结果集的一部分直接返回;

    - 从索引 (city,name) 取下一个记录主键 id;

    - 重复步骤 2、3,直到查到第 1000 条记录,或者是不满足 city='杭州’条件时循环结束。

六:排序字段加索引的优点

  - 在排序字段有索引的情况下,查询过程不需要临时表,也不需要排序。

  - 同时,也不会扫描全部符合条件的行数,而是找到适合条件既会返回数据。

七:其他在排序中中需要注意的。

  - 无条件查询如果只有order by create_time,即便create_time上有索引,也不会使用到。

    - 因为优化器认为走二级索引再去回表成本比全表扫描排序更高。所以选择走全表扫描,然后根据老师讲的两种方式选择一种来排序

  - 无条件查询但是是order by create_time limit m.如果m值较小,是可以走索引的.

    - 因为优化器认为根据索引有序性去回表查数据,然后得到m条数据,就可以终止循环,那么成本比全表扫描小,则选择走二级索引。

    - 即便没有二级索引,mysql针对order by limit也做了优化,采用堆排序。

《Mysql - Order By 的工作原理?》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. FCS省选模拟赛 Day4

    传送门 Solution Code  /* 斯坦纳树:O(n*3^n+kE*2^n) 暂且把O(k*E)当成是spfa的复杂度 15:15~16:20 原题:bzoj_4774 */ #include ...

  2. Java 基础:Map的一家

    0.Java中的集合框架 1.Map--接口 public interface Map<K,V> 包:java.util.Map Map提供了一种映射关系,其中的元素是以键值对(key-v ...

  3. Java 学习之路(2)程序基本要素

    编写一个程序,基本要素包括:标识符.关键字.注释.修饰符.块.语句.类和main()方法. 标识符 概念 在Java语言中:标识符是用来给类.对象.方法.变量.接口和自定义数据类型命名的. 标识符组成 ...

  4. java读取文件内容并输出到控制台,java中实现文件复制

    public class TestFileInputStream { public static void main(String [] args) { //读取指定文件中内容,并在控制台输出 Fil ...

  5. mac环境使用python处理protobuf

    安装 brew install protobuf 然后再安装protobuf需要的依赖 brew install autoconf automake libtool 验证是否安装成功 protoc – ...

  6. lol英雄时刻

    2019.5.30 翻出了当年人生中第一次LOL五杀截图...我用佐伊拿五杀了! 第一次五杀超激动的

  7. make 实例 一 3463

    ######################################################################### # # Makefile used for buil ...

  8. Qt Creater-特殊注释TODO,FIXME

    简述 TODO: + 说明: 如果代码中有该标识,说明在标识处有功能代码待编写,待实现的功能在说明中会简略说明. FIXME: + 说明: 如果代码中有该标识,说明标识处代码需要修正,甚至代码是错误的 ...

  9. eQTL | Expression quantitative trait loci | 表达数量性状基因座 | QTL | 数量性状位点

    到底什么是eQTL? eQTL和QTL之间有什么联系?为什么说QTL比eQTL难很多? QTL和GWAS有什么关系? GTEx数据库里的eQTL数据如何利用? 说eQTL之前必须先解释QTL,QTL, ...

  10. sass - &的作用

    6.8. & in SassScript 就像在选择器中使用时一样,&在SassScript中引用当前父选择器.它是一个逗号分隔的列表和空格分隔的列表.例如: .foo.bar .ba ...