一:概述

  - 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. [WEB安全]无回显代码执行【转载】

    原作者:AdminTony 原文链接:http://www.admintony.com/无回显代码执行利用方法.html 在Root-Me上有一道代码执行的题目,其链接为题目链接 0x01 简介 打开 ...

  2. 数据结构Java版之深度优先-图(十二)

    这里用深度优先遍历存在矩阵里面的图. 深度优先利用的是栈的FIFO特性.为此遍历到底后,可以找到最相邻的节点继续遍历.实现深度优先,还需要在节点加上一个访问标识,来确定该节点是否已经被访问过了. 源码 ...

  3. cmake和json安装

    一.cmake源码安装 官网下载源码:https://cmake.org/download/ 安装: ./bootstrap make make install cmake --version 二.j ...

  4. windows命令行操作

    一.打开方式 -  开始菜单  -->  运行 -->  输入cmd -->  回车 二.常用的指令 dir                             - 列出当前目录 ...

  5. ubuntu之路——day8.4 Adam自适应矩估计算法

    基本上讲,Adam就是将day8.2提到的momentum动量梯度下降法和day8.3提到的RMSprop算法相结合的优化算法 首先初始化 SdW = 0 Sdb = 0 VdW = 0 Vdb = ...

  6. GWAS这十年 | 10 Years of GWAS Discovery: Biology, Function, and Translation

    相关文章: A Unified Framework for Association Analysis with Multiple Related Phenotypes 太重要了,不得不单独拿出来分析一 ...

  7. HttpWebrequest使用的注意点

    HttpWebrequest使用的注意点 1.HttpWebrequest相关属性的设置以及默认连接数量限制 System.Net.ServicePointManager.DefaultConnect ...

  8. mariadb galera群集故障记录

    负责galera上执行删除语句 delete from t1 where group_id= and group_id=; 执行后,群集破坏,除了主节点存活,其他俩个节点全都停掉. 查看galera的 ...

  9. Flutter -------- 新手 WanAndroid 项目练习

    一个简单Flutter项目wanandroid,先前用Kotlin来开发过,适合新手练习. 用到的库 包含功能: http+数据解析 网络请求数据列表展示 Banner轮播 WebView跳转详情 D ...

  10. 【MySQL】Mac通过brew安装的MySQL重启方法

    问题 在 Mac 上通过 brew install mysql 安装的的MySQL使用基本MySQL命令重启会失败: mysql.server stop mysql.server start mysq ...