一:概述

  - 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. 2、ES6结构赋值和模板字符串

    ES6允许按照一定的模式,从数组和对象中提取值,这被称为结构,即解开数据的结构 1.数组的解构赋值 let [a,b] = [1,2] let [a,b,c=100] = [1,2] //c的默认值为 ...

  2. CSS显示模式

    div和span标签 1.容器级的标签中可以嵌套其他所有的标签(div->一般用于配合CSS完成网页的基本布局.h.ul.ol.dl.li.dt.dd......),文本级的标签中只能嵌套文字/ ...

  3. 团队作业-Alpha(1/4)

    队名:软工9组 组长博客: https://www.cnblogs.com/cmlei/ 作业博客: 组员进度 ● 组员一(组长) 陈明磊 ○过去两天完成了哪些任务 ●文字/口头描述 初步学习flas ...

  4. Java查询目录下的所有文件(包括子目录)

    目录图: 方法代码: /** * 读取目录下的所有文件 * * @param dir * 目录 * @param fileNames * 保存文件名的集合 * @return */ public st ...

  5. GWAS 全基因组关联分析 | summary statistic 概括统计 | meta-analysis 综合分析

    有很多概念需要明确区分: 人有23对染色体,其中22对常染色体autosome,另外一对为性染色体sex chromosome,XX为女,XY为男. 染色体区带命名:在标示一特定的带时需要包括4项:① ...

  6. 其他系列 | charles抓取https中出现unknow【转载】

    原文:https://www.cnblogs.com/aeolian/p/9249185.html http正常抓包,https则出现unknown 1.安装证书 Help->SSL Proxy ...

  7. Mysql修改数据文件默认目录datadir

    1.停止服务 service mysql stop service mysqld stopmysqladmin -uroot shutdown -p 2.创建目录 cd /data mkdir mys ...

  8. Kotlin集合——List集合

    Kotlin集合——List集合 转 https://www.jianshu.com/p/3f3bb4943638   List集合的最大特征就是集合元素都有对应的顺序索引.List集合允许使用重复元 ...

  9. Python3基础 函数 多值参数 元组与字典形式(键值对分别指出)

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  10. Flutter修改应用图标及图标

    应用名称是需要在 Android 和 iOS 中分别调整的:Android 是在 AndroidManifest.xml 中修改:iOS 则是在 Info.plist 中修改的: 如果需要更改应用的 ...