一:概述

  - 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. Flink(一) —— 启动与基本使用

    一.Flink概念 lambda架构 将离线计算和实时计算结合在一起,发挥离线计算准确率高.实时计算响应速度快的优势.缺点是,同一套逻辑要分别在两个模式下实现,存在代码冗余的问题. Flink特点 ( ...

  2. 谷歌分析(Google Analytics) 是什么

    谷歌分析(Google Analytics) 是什么 一.总结 一句话总结: 谷歌分析,即大家俗称的ga,全称google analytics,是谷歌推出的网站流量分析工具,可以说是当前业界最强大的流 ...

  3. QT中显示动画

    在QT中要显示GIF图片,不能通过单单的添加部件来完成.还需要手动的编写程序.工具:QT Creator新建一个工程,我们先在designer中,添加一个QLabel部件. 将QLabel拉成适当大小 ...

  4. PHP是单线程还是多线程?

    PHP 从设计之初到流行起来都没有出现明显需要用多线程才能解决的需求.某些需要用到多线程的地方也有相应的解决方案和替代方案.多线程并不总是比单线程优,多线程可能会引入其他问题(例如:两个线程同时调用一 ...

  5. 使用idea创建第一个springboot项目

    版权声明:版权归作者所有,转载请注明出处. https://blog.csdn.net/qq_34205356/article/details/81098354 前言:如今springboot越来越火 ...

  6. 当fixed元素相互嵌套时,父元素会影响子元素的层叠关系,最好不要嵌套使用fixed

    问题:fixed元素被另一个fixed元素包含的时候在chrome下fixed子元素的定位会受到父元素的影响. 解释:层叠关系是受层叠上下文影响的.文档中的层叠上下文由满足以下任意一个条件的元素形成: ...

  7. flutter -------- 页面跳转和传值

    在安卓原生开发中,页面跳转可以用Intent类来具体实现: Intent intent =new Intent(MainActivity.this,second.class); startActivi ...

  8. ZingChart 隐藏数据点

    正常情况下 zingChart 的数据点会显示到图表中,但是如果数据点很多的情况下,可能会让你无法准确的预测趋势,而且也不美观 在 js 配置中添加最多允许显示的数据点,超过这个值将不显示数据点 效果 ...

  9. viewSwitcher 切换视图

    通过VIewSwitcher切换视图.这个用到了baseAdapter,还是不太懂,先记个笔记. <RelativeLayout xmlns:android="http://schem ...

  10. git-scm教程摘要

    Git 有三种状态 已提交(committed).已修改(modified)和已暂存(staged) 已提交表示数据已经安全的保存在本地数据库中. 已修改表示修改了文件,但还没保存到数据库中. 已暂存 ...