研发日常踩坑-Mysql分页数据重复

这篇具有很好参考价值的文章主要介绍了研发日常踩坑-Mysql分页数据重复。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

踩坑描述:

写分页查询接口,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结合实现。

作者:京东零售 马成龙

来源:京东云开发者社区 转载请注明来源文章来源地址https://www.toymoban.com/news/detail-710879.html

到了这里,关于研发日常踩坑-Mysql分页数据重复的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 日常踩坑:Java中double类型出现科学计数法问题

    背景:在与银行的项目对接中,近期客户反馈支付失败,错误信息是:“付款金额格式有问题”,经过日志分析,发现客户系统发送银行系统时,付款金额以科学计数法的形式传递参数。 重现: 经过测试发现,浮点数(double、float)当整数部分超过7位以上(不含7位),就会

    2024年02月16日
    浏览(44)
  • 小程序onReachBottom上拉触底/下拉刷新没有反应问题(日常踩坑)

    今天踩了一个坑,因为改之前同事写的页面,新功能需要用到上拉刷新获取更多数据,当我加上onReachBottom时不管怎么上拉都没有效果后来发现给了整个页面固定高度,这就导致onReachBottom不触发了,其实还有很多导致onReachBottom不触发的,比如使用scroll-view处理不当也会导致o

    2024年02月03日
    浏览(39)
  • 【日常踩坑】解决 pip 安装第三方包时因 SSL 报错

    好久没用 python ,最近重新下载安装好 python 后发现用 pip 安装第三方包一直失败。经过一番折腾发现,如果报错信息符合下面两种,一般都是因为网络连接时 SSL 认证失败导致的 check_hostname requires server_hostname raise ValueError(\\\"check_hostname requires server_hostname\\\") ValueError: check_hostname

    2023年04月12日
    浏览(47)
  • MySQL 根据多字段查询重复数据

    在实际的数据库应用中,我们经常需要根据多个字段来查询重复的数据。MySQL 提供了一些方法来实现这个功能,让我们能够快速准确地找到和处理重复数据。本文将介绍如何使用 MySQL 来根据多字段查询重复数据,并提供相应的代码示例。 什么是重复数据? 重复数据指的是在

    2024年02月06日
    浏览(55)
  • MySQL去除数据库重复记录

    要从MySQL数据库中删除重复的记录,您可以使用 DELETE 语句结合 GROUP BY 和 HAVING 子句来实现。以下是一个示例: 在上述示例中,您需要将 your_table 替换为您的表名,并将 column1, column2, ... 替换为用于判断重复的列名。这个查询将删除所有重复的记录,只保留每组重复记录中的一

    2024年02月11日
    浏览(61)
  • 【word日常操作】word里面表格已经设置了重复标题行,但是显示无效怎么办

    在制作表格的过程当中,相信很多人都知道,表格不只有一页的时候就会在下一面,也会显示出来,然而这时我们需要让word表头重复出现,那么该怎么办呢? word表格如何设置多页时能重复表头,百度后出现了如下步骤: 按照上述步骤设置后,如下所示: 点击确定后,下一页

    2024年02月08日
    浏览(47)
  • Mysql 删除重复数据保留一条有效数据

    ============================== ©Copyright 蕃薯耀 2023-01-31 蕃薯耀的博客_CSDN博客-蕃薯耀分享,java,js领域博主 原理: 根据字段对数据进行分组,查询出所有分组的最小ID(即要保留的不重复数据) 将查询出来的数据(所有不重复的数据)存放到临时表中 从原来的表中删除ID不在临时表

    2024年02月16日
    浏览(48)
  • 国内优秀的开源低代码框架:PagePlug,面向研发使用,拒绝重复、低价值的工单循环开发

    分享下Appsmith中文版的PagePlug吧, 开源、面向研发人员开发使用的低代码: PagePlug将开发人员的开发时间减少了 60%,PP框架本身解决了很多没必要的繁重工作。 前者appsmith目前是github上超29K最火的开源低代码平台,后者PagePlug也是目前国内开源社区比较火的低代码平台—— 针

    2024年02月09日
    浏览(35)
  • 【常用SQL】MySQL查询重复的数据

    查询重复的数据可以使用SQL中的GROUP BY和HAVING子句。以下是一个示例查询,可以检查名为 table_name 的表中是否有重复的 column_name 列的值: 该查询将按照 column_name 列的值进行分组,并计算每个值的出现次数。然后使用HAVING子句过滤出现次数大于1的组,这些组中的行即为重复数

    2024年02月16日
    浏览(57)
  • MySQL:插入数据insert ignore,重复数据自动忽略

    MySQL中插入数据,如果插入的数据在表中已经存在(主键或者唯一键已存在),使用insert ignore 语法可以忽略插入重复的数据。 1、insert ignore 语法 使用insert ignore语法插入数据时,如果发生主键或者唯一键冲突,则忽略这条插入的数据。 满足以下条件之一: 主键重复 唯一键重

    2024年02月12日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包