Mysql order by与limit混用陷阱
在Mysql中我们常常用order by来进行排序,使用limit来进行分页,当需要先排序后分页时我们往往使用类似的写法select * from 表名 order by 排序字段 limt M,N。但是这种写法却隐藏着较深的使用陷阱。在排序字段有数据重复的情况下,会很容易出现排序结果与预期不一致的问题。
比如现在有一张user表,表结构及数据如下:
现在想根据创建时间升序查询user表,并且分页查询,每页2条,那很容易写出sql为:select * from user order by create_time limit pageNo,2;
在执行查询过程中会发现:
1、查询第一页数据时:
2、查询第四页数据时:
user表共有8条数据,有4页数据,但是实际查询过程中第一页与第四页竟然出现了相同的数据。
这是什么情况?难道上面的分页SQL不是先将两个表关联查询出来,然后再排好序,再取对应分页的数据吗???
上面的实际执行结果已经证明现实与想像往往是有差距的,实际SQL执行时并不是按照上述方式执行的。这里其实是Mysql会对Limit做优化,具体优化方式见官方文档:https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
这个是5.7版本的说明,提取几个问题直接相关的点做下说明。
上面官方文档里面有提到如果你将Limit row_count与order by混用,mysql会找到排序的row_count行后立马返回,而不是排序整个查询结果再返回。如果是通过索引排序,会非常快;如果是文件排序,所有匹配查询的行(不带Limit的)都会被选中,被选中的大多数或者全部会被排序,直到limit要求的row_count被找到了。如果limit要求的row_count行一旦被找到,Mysql就不会排序结果集中剩余的行了。
这里我们查看下对应SQL的执行计划:
可以确认是用的文件排序,表确实也没有加额外的索引。所以我们可以确定这个SQL执行时是会找到limit要求的行后立马返回查询结果的。
不过就算它立马返回,为什么分页会不准呢?
官方文档里面做了如下说明:
如果order by的字段有多个行都有相同的值,mysql是会随机的顺序返回查询结果的,具体依赖对应的执行计划。也就是说如果排序的列是无序的,那么排序的结果行的顺序也是不确定的。
基于这个我们就基本知道为什么分页会不准了,因为我们排序的字段是create_time,正好又有几个相同的值的行,在实际执行时返回结果对应的行的顺序是不确定的。对应上面的情况,第一页返回的name为8的数据行,可能正好排在前面,而第四页查询时name为8的数据行正好排在后面,所以第四页又出现了。
那这种情况应该怎么解决呢?
官方给出了解决方案:
如果想在Limit存在或不存在的情况下,都保证排序结果相同,可以额外加一个排序条件。例如id字段是唯一的,可以考虑在排序字段中额外加个id排序去确保顺序稳定。
所以上面的情况下可以在SQL再添加个排序字段,比如fund_flow的id字段,这样分页的问题就解决了。修改后的SQL可以像下面这样:
SELECT * FROM user ORDER BY create_time,id LIMIT 6,2;
再次测试问题解决!!
扩展介绍:
Mysql Order by排序原理
Mysql order by与limit混用陷阱的更多相关文章
- MySQL在大数据Limit使用
它已被用于Oracle一世.但今天,很惊讶,MySQL在对数量级的性能,甚至差距如此之大不同的顺序相同的功能. 看看表ibmng(id,title,info) 只要 id key 指数title ...
- MySQL 中随机抽样:order by rand limit 的替代方案
最近由于需要大概研究了一下MYSQL的随机抽取实现方法.举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RA ...
- MySQL ORDER BY主键id加LIMIT限制走错索引
背景及现象 report_product_sales_data表数据量2800万: 经测试,在当前数据量情况下,order by主键id,limit最大到49的时候可以用到索引report_produ ...
- mysql同时使用order by和limit查询时的一个严重隐患 -- 丢失数据
转自: https://blog.csdn.net/tsxw24/article/details/44994835 我经常使用order by和limit来做数据分页显示并排序,一直也没发现过什么问题 ...
- MySQL中 order by 与 limit 的执行顺序以及使用实例
在 MySQL 执行查询的时候,我们可能既要对结果集进行排序又要限制行数,那么此时 order by 与 limit 的执行顺序是怎么样的呢? order by与limit的执行顺序是:先执行orde ...
- 采坑笔记——mysql的order by和limit排序问题
背景说明 今天写出一个十分弱智的bug,记录一下,提醒自己以后别这种犯错,不怕丢人哈~ 在写一个分页查询记录的sql时,要根据添加的时间逆序分页输出,之前的写法是酱紫 select record.a, ...
- MySQL中 ORDER BY 与 LIMIT 的执行顺序
如下: ORDER BY 与 LIMIT 的执行顺序:ORDER BY > LIMIT ORDER BY 与 LIMIT 的编写顺序:ORDER BY > LIMIT 正确写法: sele ...
- 为什么MYSQL分页时使用limit+ order by会出现数据重复问题
问题描述: MYSQL采用limit进行翻页查询时,搭配order by ,在翻到第二页的时候可能会出现第一页的数据, 示例sql如下: select a,b from c where d = ' ...
- MYSQL随机抽取查询 MySQL Order By Rand()效率问题
MYSQL随机抽取查询:MySQL Order By Rand()效率问题一直是开发人员的常见问题,俺们不是DBA,没有那么牛B,所只能慢慢研究咯,最近由于项目问题,需要大概研究了一下MYSQL的随机 ...
随机推荐
- Spring(1)—初识
Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用. 特点: 轻量--从大小与开销两方面而言Spring都是轻量的. 控 ...
- flask之基于DBUtils实现数据库连接池、本地线程、上下文
本篇导航: 数据库连接池 本地线程 上下文管理 面向对象部分知识点解析 1.子类继承父类__init__的三种方式 class Dog(Animal): #子类 派生类 def __init__(se ...
- WPF之几何图形Geometry
在WPF的DrawingContext对象中,提供了基本的绘制椭圆和矩形的API:DrawEllipse和DrawRectangle.但是,这些是远远不够用的,我们在日常应用中,更多的是使用DrawG ...
- 11、TopN实战
1.Java版本: 1.1.取前3 package sparkcore.java; import java.util.List; import org.apache.spark.SparkConf; ...
- Git上传空文件夹
git上传的文件夹为空的时候 1,先删除空的文件夹 参考:https://www.cnblogs.com/wang715100018066/p/9694532.html 2,这个只能说是技巧不能说是方 ...
- SSE图像算法优化系列二十一:基于DCT变换图像去噪算法的进一步优化(100W像素30ms)。
在优化IPOL网站中基于DCT(离散余弦变换)的图像去噪算法(附源代码) 一文中,我们曾经优化过基于DCT变换的图像去噪算法,在那文所提供的Demo中,处理一副1000*1000左右的灰度噪音图像耗时 ...
- Teigha.NET开发入门1- Teigha介绍
对于CAD开发,无疑较强大的方式是Lisp.AutoCAD二次开发,且学习资源丰富,依靠强大的AutoCAD的环境可以干很多事,省很多力.但若要脱离AutoCAD环境,那就当属Teigha了. 名称问 ...
- IDEA修改JDK(全)
https://www.cnblogs.com/hkgov/p/8074085.html 解决:javac: 无效的目标发行版: 1.8 解决:项目JDK版本不对 解决:Jar包问题 1," ...
- Canvas 旋转的图片
var image = new Image(), counter = 0; image.onload = function () { var CANVAS_WIDTH = 300, CANVAS_HE ...
- dagger2 重点笔记
官方架构例子,里面有个dagger2的结合的例子 https://github.com/googlesamples/android-architecture https://google.github ...