位置: 编程技术 - 正文

浅谈MySQL排序原理与案例分析(mysql数据库排序)

编辑:rootadmin

推荐整理分享浅谈MySQL排序原理与案例分析(mysql数据库排序),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:mysql 排序原理,mysql的排序语句,mysql排序语法,mysql顺序排列,mysql排序规则选什么,mysql中排序怎么写,mysql的排序语句,mysql 排序原理,内容如对您有帮助,希望把文章链接给更多的朋友!

前言

排序是数据库中的一个基本功能,MySQL也不例外。用户通过Order by语句即能达到将指定的结果集排序的目的,其实不仅仅是Order by语句,Group by语句,Distinct语句都会隐含使用排序。本文首先会简单介绍SQL如何利用索引避免排序代价,然后会介绍MySQL实现排序的内部原理,并介绍与排序相关的参数,最后会给出几个“奇怪”排序例子,来谈谈排序一致性问题,并说明产生现象的本质原因。

1.排序优化与索引使用

为了优化SQL语句的排序性能,最好的情况是避免排序,合理利用索引是一个不错的方法。因为索引本身也是有序的,如果在需要排序的字段上面建立了合适的索引,那么就可以跳过排序的过程,提高SQL的查询速度。下面我通过一些典型的SQL来说明哪些SQL可以利用索引减少排序,哪些SQL不能。假设t1表存在索引key1(key_part1,key_part2),key2(key2)

a.可以利用索引避免排序的SQL

b.不能利用索引避免排序的SQL

2.排序实现的算法

对于不能利用索引避免排序的SQL,数据库不得不自己实现排序功能以满足用户需求,此时SQL的执行计划中会出现“Using filesort”,这里需要注意的是filesort并不意味着就是文件排序,其实也有可能是内存排序,这个主要由sort_buffer_size参数与结果集大小确定。MySQL内部实现排序主要有3种方式,常规排序,优化排序和优先队列排序,主要涉及3种排序算法:快速排序、归并排序和堆排序。假设表结构和SQL语句如下:

a.常规排序(1).从表t1中获取满足WHERE条件的记录(2).对于每条记录,将记录的主键+排序键(id,col2)取出放入sort buffer(3).如果sort buffer可以存放所有满足条件的(id,col2)对,则进行排序;否则sort buffer满后,进行排序并固化到临时文件中。(排序算法采用的是快速排序算法)(4).若排序中产生了临时文件,需要利用归并排序算法,保证临时文件中记录是有序的(5).循环执行上述过程,直到所有满足条件的记录全部参与排序(6).扫描排好序的(id,col2)对,并利用id去捞取SELECT需要返回的列(col1,col2,col3)(7).将获取的结果集返回给用户。从上述流程来看,是否使用文件排序主要看sort buffer是否能容下需要排序的(id,col2)对,这个buffer的大小由sort_buffer_size参数控制。此外一次排序需要两次IO,一次是捞(id,col2),第二次是捞(col1,col2,col3),由于返回的结果集是按col2排序,因此id是乱序的,通过乱序的id去捞(col1,col2,col3)时会产生大量的随机IO。对于第二次MySQL本身一个优化,即在捞之前首先将id排序,并放入缓冲区,这个缓存区大小由参数read_rnd_buffer_size控制,然后有序去捞记录,将随机IO转为顺序IO。b.优化排序常规排序方式除了排序本身,还需要额外两次IO。优化的排序方式相对于常规排序,减少了第二次IO。主要区别在于,放入sort buffer不是(id,col2),而是(col1,col2,col3)。由于sort buffer中包含了查询需要的所有字段,因此排序完成后可以直接返回,无需二次捞数据。这种方式的代价在于,同样大小的sort buffer,能存放的(col1,col2,col3)数目要小于(id,col2),如果sort buffer不够大,可能导致需要写临时文件,造成额外的IO。当然MySQL提供了参数max_length_for_sort_data,只有当排序元组小于max_length_for_sort_data时,才能利用优化排序方式,否则只能用常规排序方式。c.优先队列排序为了得到最终的排序结果,无论怎样,我们都需要将所有满足条件的记录进行排序才能返回。那么相对于优化排序方式,是否还有优化空间呢?5.6版本针对Order by limit M,N语句,在空间层面做了优化,加入了一种新的排序方式--优先队列,这种方式采用堆排序实现。堆排序算法特征正好可以解limit M,N 这类排序的问题,虽然仍然需要所有元素参与排序,但是只需要M+N个元组的sort buffer空间即可,对于M,N很小的场景,基本不会因为sort buffer不够而导致需要临时文件进行归并排序的问题。对于升序,采用大顶堆,最终堆中的元素组成了最小的N个元素,对于降序,采用小顶堆,最终堆中的元素组成了最大的N的元素。

3.排序不一致问题

案例1

Mysql从5.5迁移到5.6以后,发现分页出现了重复值。测试表与数据:

假设每页3条记录,第一页limit 0,3和第二页limit 3,3查询结果如下:

我们可以看到 id为4的这条记录居然同时出现在两次查询中,这明显是不符合预期的,而且在5.5版本中没有这个问题。产生这个现象的原因就是5.6针对limit M,N的语句采用了优先队列,而优先队列采用堆实现,比如上述的例子order by c1 asc limit 0,3 需要采用大小为3的大顶堆;limit 3,3需要采用大小为6的大顶堆。由于c1为2的记录有3条,而堆排序是非稳定的(对于相同的key值,无法保证排序后与排序前的位置一致),所以导致分页重复的现象。为了避免这个问题,我们可以在排序中加上唯一值,比如主键id,这样由于id是唯一的,确保参与排序的key值不相同。将SQL写成如下:

案例2

两个类似的查询语句,除了返回列不同,其它都相同,但排序的结果不一致。测试表与数据:

浅谈MySQL排序原理与案例分析(mysql数据库排序)

分别执行SQL语句:

执行结果如下:

看看两者的执行计划是否相同

为了说明问题,我在语句中加了force index的hint,确保能走上c1列索引。语句通过c1列索引捞取id,然后去表中捞取返回的列。根据c1列值的大小,记录在c1索引中的相对位置如下:

(c1,id)===(b,6),(b,3),(5,c),(c,2),对应的status值分别为2 3 2 4。从表中捞取数据并按status排序,则相对位置变为(6,2,b),(5,2,c),(3,3,c),(2,4,c),这就是第二条语句查询返回的结果,那么为什么第一条查询语句(6,2,b),(5,2,c)是调换顺序的呢?这里要看我之前提到的a.常规排序和b.优化排序中标红的部分,就可以明白原因了。由于第一条查询返回的列的字节数超过了max_length_for_sort_data,导致排序采用的是常规排序,而在这种情况下MYSQL将rowid排序,将随机IO转为顺序IO,所以返回的是5在前,6在后;而第二条查询采用的是优化排序,没有第二次捞取数据的过程,保持了排序后记录的相对位置。对于第一条语句,若想采用优化排序,我们将max_length_for_sort_data设置调大即可,比如。

下面是本人关于mysql 自定义排序(field,INSTR,locate)的一点心得,希望对大家有所帮助首先说明这里有三个函数(order by field,ORDER BY INSTR,ORDER BY locate)

原表:

下面是我执行后的结果:

根据结果分析:order by field(2,3,5,4,1,6) 结果显示顺序为:1 3 4 5 6 2

根据结果分析:order by field(2,3,5,4,1,6) 结果显示顺序为:2 1 3 4 5 6

根据结果分析:order by INSTR(2,3,5,4,1,6) 结果显示顺序为:1 6 2 3 5 4

根据结果分析:order by INSTR(2,3,5,4,1,6) 结果显示顺序为:4 5 3 2 1 6

id user pass

根据结果分析:order by locate(2,3,5,4,1,6) 结果显示顺序为:1 6 2 3 5 4

根据结果分析:order by locate(2,3,5,4,1,6) 结果显示顺序为:4 5 3 2 1 6如我想要查找的数据库中的ID顺序首先是(2,3,5,4)然后在是其它的ID顺序,你首先要把他降序排即(4 5 3 2),然后在 SELECT * FROM `user` ORDER BY INSTR( '4,5,3,2', id ) DESC limit 0, 或用 SELECT * FROM `user` ORDER BY locate( id, '4,5,3,2' ) DESC 就得到你想要的结果了。

MySQLMerge存储引擎 MERGE存储引擎把一组MyISAM数据表当做一个逻辑单元来对待,让我们可以同时对他们进行查询。构成一个MERGE数据表结构的各成员MyISAM数据表必须具有完全

理解MySQL变量和条件 一、概述变量在存储过程中会经常被使用,变量的使用方法是一个重要的知识点,特别是在定义条件这块比较重要。mysql版本:5.6二、变量定义和赋值#

理解Mysql prepare预处理语句 MySQL5.1对服务器一方的预制语句提供支持。如果您使用合适的客户端编程界面,则这种支持可以发挥在MySQL4.1中实施的高效客户端/服务器二进制协议的优

标签: mysql数据库排序

本文链接地址:https://www.jiuchutong.com/biancheng/319770.html 转载请保留说明!

上一篇:更改Mysql root用户密码

下一篇:MySQLMerge存储引擎(mysql数据表存储引擎)

  • 企业清算过程中发生的费用
  • 冲减计提
  • 一般纳税人附加税优惠政策2023
  • 电信没有基站为什么信号也很好
  • 成本法长期股权投资账务处理
  • 实收资本变更股东要交税吗
  • 外资企业银行贷款限制
  • 收入做多增值税怎么算
  • 企业车辆办理违章
  • 出售固定资产要交哪些税
  • 企业发生的运输费用怎么做账?
  • 财务报表的总投资怎么算
  • 公司必须购买税控设备吗
  • 冲销凭证怎么记账
  • 既销售货物又提供劳务例题
  • 发票的开具时效为
  • 房地产增值税如何抵扣
  • 小规模纳税人销售收入会计分录
  • 已知不含税金额和增值税如何计算税率
  • 职工餐厅账务处理
  • 雇主责任保险
  • 有进项没有销项会计处理
  • 进项税额暂不转出情况说明怎么写
  • 吸甲醛最好的植物是什么?
  • 如何在excel中取最早与最晚
  • Windows10如何解压rar
  • 有限责任公司注册要求
  • 读会计没有考到证 能出来干什么
  • 自产自用产品的会计处理
  • 收到折扣发票怎么处理
  • 存出投资款现金流量表选什么
  • 鸿蒙系统小艺怎么改声音
  • 除了个税还有什么税
  • 个人所得税计提缴纳会计分录
  • 存货发生了减值怎么处理
  • 城市里创业
  • 异构图神经网络 电影推荐
  • php addslashes函数
  • 非洲加纳霍霍埃族是个国家吗
  • 普通发票的开票规定
  • PHP isset()与empty()的使用区别详解
  • 蓝桥杯第十四届模拟赛第三期
  • vue.js前端
  • 强制缓存与协商缓存的区别
  • python中模块的用法
  • 公司买东西了怎么做账
  • 企业实际发生的与取得收入有关的支出
  • 物业费税目
  • 增值税进项加计抵减账务处理
  • 建造合同新准则
  • 工程施工会计科目是什么科目
  • 工业企业制造费用包括哪些
  • 暂估有几种处理方法
  • 企业销售退回的论文
  • 律师费能计入办公费吗合法吗
  • 加班餐费报销计入什么费用
  • 企业股东的出资方式
  • 年末本年利润怎么转到未分配利润
  • 固定资产专票可以不抵扣吗
  • 结账时能否用红笔写名字
  • CentOS7下MySQL5.7安装配置方法图文教程(YUM)
  • 苹果mac安装
  • wind8系统怎么清除所有东西 恢复出厂
  • dll文件应该放在哪里
  • SchSvr.exe - SchSvr是什么进程 有什么作用
  • node.js的使用
  • 批处理删除注册表指定项
  • perl格式化输出
  • 权作记录 cocos2dx
  • Android:wpa_supplicant决定选择哪种驱动
  • python利用matplotlib将扇形平分成50份
  • 用jQuery的AJax实现异步访问、异步加载
  • cocos2d怎么用
  • Unity3D游戏开发标准教程
  • js怎么设置图片大小
  • python获取linux磁盘信息
  • 上海增值税怎么报税流程
  • 福州税务局几点关门
  • 上海纳税总额
  • 社会救助档案管理规范化的好处
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设