踩坑描述:

写分页查询接口,order by和limit混用的时候,出现了排序的混乱情况 在进行第N页查询时,出现与第一前面页码的数据一样的记录。

问题

在MySQL中分页查询,我们经常会用limit,如:limit(0,20)表示查询第一页的20条数据,limit(20,20)表示查询第二页的数据。业务上我们通常也会在分页的时候加上排序 order by;

但是当limit和order by一起使用的时候,有可能会出现第N页的数据,竟然和前面页码的数据有重复

例如:

SELECT a,b FROM table WHERE c=1 ORDER BY d desc LIMIT 0,20

使用上述SQL查询的时候,很有可能和LIMIT 20,20查出相同的某条数据。为了解决这个问题,我们在ORDER BY后面加上了ID(唯一索引页可以)排序来进行规避,

如下:

SELECT a,b FROM table WHERE c=1 ORDER BY d desc,id desc LIMIT 0,20

理论上,MySQL的排序默认情况下是以主键ID作为排序条件的,也就是说,如果在条件d相等的情况下,主键id会作为默认的排序条件,不需要我们多此一举加ID asc。但是事实就是,MySQL在order by和limit同时使用的情况下,出现了排序的混乱情况

分析

在MySQL 5.6的版本上,优化器在遇到order by+limit语句的时候,做了一个优化,使用了priority queue

使用 priority queue 的目的,就是在不能使用索引有序性的时候,如果要排序,并且使用了limit n,那么只需要在排序的过程中,保留n条记录即可,这样虽然不能解决所有记录都需要排序的开销,但是只需要 sort buffer 少量的内存就可以完成排序

之所以MySQL 5.6出现了第二页数据重复的问题,是因为 priority queue 使用了堆排序的排序方法,而堆排序是一个不稳定的排序方法,也就是相同的值可能排序出来的结果和读出来的数据顺序不一致。

MySQL 5.5 没有这个优化,所以也就不会出现这个问题。

也就是说,MySQL 5.5是不存在本文提到的问题的,5.6版本之后才出现了这种情况。

(1)     SELECT 
(2)     DISTINCT <select_list>
(3)     FROM <left_table>
(4)     <join_type> JOIN <right_table>
(5)     ON <join_condition>
(6)     WHERE <where_condition>
(7)     GROUP BY <group_by_list>
(8)     HAVING <having_condition>
(9)     ORDER BY <order_by_condition>
(10)    LIMIT <limit_number>

执行顺序依次为 form… where… select… order by… limit…,由于上述priority queue的原因,在完成select之后,所有记录是以堆排序的方法排列的,在进行order by时,仅把d值大的往前移动。但由于limit的因素,排序过程中只需要保留到20条记录即可,d并不具备索引有序性,所以当第二页数据要展示时,mysql见到哪一条就拿哪一条,因此,当排序值相同的时候,第一次排序是随意排的,第二次再执行该sql的时候,其结果应该和第一次结果有可能一样。

解决方法

1.尽量使用不重复的值进行排序

如果在字段添加上索引,就直接按照索引的有序性进行读取并分页(这个字段如果有重复值分页会有可能出现重复)。

可以最后加上ID排序,也不会影响业务

2.正确理解分页

分页是建立在排序的基础上,进行了数量范围分割。排序是数据库提供的功能,而分页却是衍生出来的应用需求。 在MySQL和Oracle的官方文档中提供了limit n和rownum < n的方法,但却没有明确的定义分页这个概念。 还有重要的一点,虽然上面的解决方法可以缓解用户的这个问题,但按照用户的理解,依然还有问题:比如,这个表插入比较频繁,用户查询的时候,在read-committed的隔离级别下,第一页和第二页仍然会有重合,这个可以使用ID来规避。 所以,分页一直都有这个问题,不同场景对数据分页都没有非常高的准确性要求。

3.一些常见的数据库排序问题

不加order by的时候的排序问题

用户在使用Oracle或MySQL的时候,发现MySQL总是有序的,Oracle却很混乱,这个主要是因为Oracle是堆表,MySQL是索引聚簇表的原因。所以没有order by的时候,数据库并不保证记录返回的顺序性,并且不保证每次返回都一致的。 分页问题-分页重复的问题 如前面所描述的,分页是在数据库提供的排序功能的基础上,衍生出来的应用需求,数据库并不保证分页的重复问题。 NULL值和空串问题 不同的数据库对于NULL值和空串的理解和处理是不一样的,比如Oracle NULL和NULL值是无法比较的,既不是相等也不是不相等,是未知的。而对于空串,在插入的时候,MySQL是一个字符串长度为0的空串,而Oracle则直接进行NULL值处理。

深分页问题

有些时候,我们需要偏移一定量数据之后,获取某些数据,就很容易想到用limit,但是,如果偏移量很大时,就会发现SQL执行起来非常非常慢了,因为,偏移量会分页读取到buffpool中,数据量大,占用的buffpool空间就会大,而这个空间大小是配置的,一般不会很大;

其次需要从一开始就扫描数据,最后要舍弃前面大量数据,只保留需要的那几条数据,而且过程还有可能需要回表操作,导致了慢sql。

对于这个问题的优化,建议写一个过滤条件(比如:自增主键ID或有序的字段),再与limit结合实现。

作者:京东零售 马成龙

来源:京东云开发者社区 转载请注明来源

研发日常踩坑-Mysql分页数据重复的更多相关文章

  1. 日常踩坑——rand()总是出现重复数据

    写了一个生成随机数组的函数,然后跑出来,结果总是…… 然后,很奇怪的是一步一步调试,它就没问题了,WTF??? 问题出在:重复写了srand(time(NULL)),只保留一个就好了. int* ge ...

  2. Mybatis oracle多表联合查询分页数据重复的问题

    Mybatis oracle多表联合查询分页数据重复的问题 多表联合查询分页获取数据时出现一个诡异的现象:数据总条数正确,但有些记录多了,有些记录却又少了甚至没了.针对这个问题找了好久,最后发现是由于 ...

  3. 解决 MySQL 分页数据错乱重复

    前言 一天,小明兴匆匆的在通讯工具上说:这边线上出现了个奇怪的问题,麻烦 DBA 大大鉴定下,执行语句 select xx from table_name wheere xxx order by 字段 ...

  4. MySQL 分页数据错乱重复

    select xx from table_name wheere xxx order by 字段A limit offset;, 表数据总共 48 条,分页数量正常,但出现了结果混杂的情况,第一页的数 ...

  5. mysql 分页数据错乱

    最近在使用mysql 分页查询数据的时候发现返回的数据与预期的不一样,显示数据重复错乱. 在官方文档 有这样一句话 If multiple rows have identical values in ...

  6. EF获取多个数据集以及MySQL分页数据查询优化

    背景:MySQL分页查询语句为 ,10; 一般页面还会获取总条数,这时候还需要一条查询总条数语句 , 这样数据库需要执行两次查询操作.MySQL提供了SQL_CALC_FOUND_ROWS追踪总条数的 ...

  7. 日常踩坑 — 相邻元素之间的margin合并问题。

    踩坑:使用v-for渲染的组件,当然图中的id已经换成class,还是没有解决这个问题,于是各种查找资料,我就不信简单的CSS问题这么难解决! v-for渲染组件级传值: <div class= ...

  8. MySQL中orderby和limit分页数据重复的问题

    背景 读取规则是按照某表中sequence字段排序的,而这个字段是让人手工填写的.那么,可想而知,数据一多,难免会出现填写的值相同的情况. 综上所述,可能就会导致以下两条sql出现数据重叠的情况: s ...

  9. SpringMVC+Mybatis实现的Mysql分页数据查询

    周末这天手痒,正好没事干,想着写一个分页的例子出来给大家分享一下. 这个案例分前端和后台两部分,前端使用面向对象的方式写的,里面用到了一些回调函数和事件代理,有兴趣的朋友可以研究一下.后台的实现技术是 ...

  10. SQL分页数据重复问题

    对于关系数据库来说,直接写SQL拉数据在列表中显示是很常用的做法.但如此便带来一个问题:当数据量大到一定程度时,系统内存迟早会耗光.另外,网络传输也是问题.如果有1000万条数据,用户想看最后一条,这 ...

随机推荐

  1. uniapp学习(一)

    [新课uniapp零基础入门到项目打包(微信小程序/H5/vue/安卓apk)全掌握] https://www.bilibili.com/video/BV1mT411K7nW/?p=24&sh ...

  2. python笔记:第四章使用字典

    1.1 概述 说白了就是键值对的映射关系 不会丢失数据本身关联的结构,但不关注数据的顺序 是一种可变类型 格式:dic = {键:值, 键:值} 键的类型:字典的键可以是任何不可变的类型,如浮点数,字 ...

  3. Jenkins自动化测试构建完成 发送钉钉消息

    背景 有时自动化测试完成后,我们可以通过构建完成后给钉钉群发消息,这样就能及时通知到所有人员了. 接入流程 1:建立钉钉机器人,可以通过群助手,添加机器人,增加WebHook自定义接入,然后添加完成会 ...

  4. BUUCTF-MISC-LSB(stegsolve的一种妙用)

    题目已知是LSB隐写 丢入stegsolve,点 > ,可以看见Red plane 0,Green plane 0,Blue plane 0上边好像有东西 点analyse->data e ...

  5. react项目中使用plop

    第一步,安装依赖 npm install plop --dev //或者用yarn yarn add plop --dev 第二步,在package同级目录下新建plopfile.js 这是plop的 ...

  6. linux内核编译中常用的目标(二)

    文章目录 一. 目标 all 或者 空 二. 目标 vmlinux 三. 目标 modules 四. 目标 Image/zImage/uImage 1.Image和zImage的区别 2.uImage ...

  7. 如何修改NuGet默认全局包文件夹的位置?

    由于一些历史原因,重装系统成为Windows用户解决疑难杂症的祖传手艺.受此影响,给硬盘分盘几乎成为了一种执念,少则C.D两个盘,夸张一点的5~6个盘的也不是没有. PS:macOS和Linux一直都 ...

  8. SQL Server 配置允许远程连接

    前言 需要别人远程你的数据库,首先需要的是在一个局域网内,或者连接的是同一个路由器,接下来就是具体步骤: 1.首先是要检查SQLServer数据库服务器中是否允许远程链接.其具体操作为: 1. 打开数 ...

  9. Three.js使用InstancedMesh实现性能优化

    1. 引言 有这么一种场景:需要渲染一座桥,桥有很多桥柱,桥柱除了位置与倾斜角度不完全相同外,其他均相同,由于桥柱数量很大,使用three.js绘制较为卡顿,如何优化?注意,要求后续能选中某个桥柱 2 ...

  10. CSS:使用透明色

    使用如下代码: background-color="#00000000"