点击上方“Java知音”,选择“置顶公众号”

技术文章第一时间送达!

作者:猿码道

www.jianshu.com/p/544c319fd838

0 问题描述

在MySQL中我们通常会采用limit来进行翻页查询,比如limit(0,10)表示列出第一页的10条数据,limit(10,10)表示列出第二页。但是,当limit遇到order by的时候,可能会出现翻到第二页的时候,竟然又出现了第一页的记录。

具体如下:

SELECT`post_title`,`post_date`
FROMpost
WHERE`post_status` = 'publish'
ORDER BYview_count desc
LIMIT5, 5

使用上述SQL查询的时候,很有可能出现和LIMIT 0,5相同的某条记录。而如果使用如下方式,则不会出现重复的情况:

SELECT*
FROMpost
WHEREpost_status = 'publish'
ORDER BYview_count desc
LIMIT5, 5

但是,由于post表的字段很多,仅仅希望用这两个字段,不想把post_content也查出来。为了解决这个情况,在ORDER BY后面使用了两个排序条件来解决这个问题,如下:

SELECT`post_title`,`post_date`
FROMpost
WHERE`post_status` = 'publish'
ORDER BYview_count desc,ID asc
LIMIT5, 5

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

1 分析问题

在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版本之后才出现了这种情况。

再看下MySQL解释sql语言时的执行顺序:

(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时,仅把view_count值大的往前移动。

但由于limit的因素,排序过程中只需要保留到5条记录即可,view_count并不具备索引有序性,所以当第二页数据要展示时,mysql见到哪一条就拿哪一条,因此,当排序值相同的时候,第一次排序是随意排的,第二次再执行该sql的时候,其结果应该和第一次结果一样。

2 解决方法

1.索引排序字段

如果在字段添加上索引,就直接按照索引的有序性进行读取并分页,从而可以规避遇到的这个问题。

2.正确理解分页

分页是建立在排序的基础上,进行了数量范围分割。排序是数据库提供的功能,而分页却是衍生出来的应用需求。

在MySQL和Oracle的官方文档中提供了limit n和rownum < n的方法,但却没有明确的定义分页这个概念。

还有重要的一点,虽然上面的解决方法可以缓解用户的这个问题,但按照用户的理解,依然还有问题:比如,这个表插入比较频繁,用户查询的时候,在read-committed的隔离级别下,第一页和第二页仍然会有重合。

所以,分页一直都有这个问题,不同场景对数据分页都没有非常高的准确性要求。

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

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

用户在使用Oracle或MySQL的时候,发现MySQL总是有序的,Oracle却很混乱,这个主要是因为Oracle是堆表,MySQL是索引聚簇表的原因。所以没有order by的时候,数据库并不保证记录返回的顺序性,并且不保证每次返回都一致的。

分页问题 分页重复的问题

如前面所描述的,分页是在数据库提供的排序功能的基础上,衍生出来的应用需求,数据库并不保证分页的重复问题。

NULL值和空串问题

不同的数据库对于NULL值和空串的理解和处理是不一样的,比如Oracle NULL和NULL值是无法比较的,既不是相等也不是不相等,是未知的。而对于空串,在插入的时候,MySQL是一个字符串长度为0的空串,而Oracle则直接进行NULL值处理。

END

Java面试题专栏

【40期】说一下线程池内部工作原理

【39期】Mybatis面试18问,你想知道的都在这里了!

【38期】一份tcp、http面试指南,常考点都给你了

【37期】请你详细说说类加载流程,类加载机制及自定义类加载器

【36期】说说 如何停止一个正在运行的线程?

【35期】谈谈你对Java线程之间通信方式的理解

【34期】谈谈为什么要拆分数据库?有哪些方法?

【33期】分别谈谈联合索引生效和失效的条件

【32期】你知道Redis的字符串是怎么实现的吗?

【31期】了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?应对措施是什么

我知道你 “在看”

小心避坑:MySQL分页时使用 limit+order by 会出现数据重复问题相关推荐

  1. layui分页limit不显示_小心避坑:MySQL分页时使用 limit+order by 会出现数据重复问题...

    20大进阶架构专题每日送达 来源:www.jianshu.com/p/544c319fd838 进入主题前先插一下,当当优惠码福利来一波!当当全场自营图书5折,用优惠码:J2JYFK(长按复制),满2 ...

  2. mysql scrapy 重复数据_小心避坑:MySQL分页时使用 limit+order by 会出现数据重复问题...

    作者:猿码道http://www.jianshu.com/p/544c319fd838 0 问题描述 在MySQL中我们通常会采用limit来进行翻页查询,比如limit(0,10)表示列出第一页的1 ...

  3. 计算机考研压分的学校,篡改分数,恶意压分...考研院校的骚操作大盘点!小心避坑!...

    篡改分数,恶意压分...考研院校的骚操作大盘点!小心避坑! 摘要:对考研的同学来说,择校是至关重要的一环.尤其是在往届考生群中,大家讨论最多的就是要不要换学校.一些同学经历了被歧视.专业课压分 作者 ...

  4. mysql分页时获得行数_MySQL分页取得总行数新法

    SELECT语句中经常用到LIMIT限制返回行数有时候可能想要知道如果没有LIMIT会返回多少行,比如做分页的时候,但又不想再执行一次相同语句. 我们要怎么做呢? 如下 在SELECT查询中包含 SQ ...

  5. 数据库MySQL分页时用的语句

    使用limit关键字.Select * from 表名 where 条件 limit 开始位置,结束位置.通过动态的改变开始和结束位置的值来实现分页.

  6. mysql插入时主键id为uuid_mysql插入数据自动生成主键uuid

    DemoMapper.java //注意方法的返回值必须是void; void add(Demo demo); ============================================ ...

  7. Mysql的避坑---- The error may involve defaultParameterMap #The error occurred while setting parameters

    Mysql的避坑---- Mysql 数据库连接添加  allowMultiQueries=true属性 最近做项目时,发现操作数据库时 sql报错,如下: ### Error updating da ...

  8. mysql分页与分页性能查询优化

    为什么80%的码农都做不了架构师?>>>    mysql分页就直接使用limit进行操作,limit如果我们直接不加任何处理可能数据大了就会很卡的. 一. 最常见MYSQL最基本的 ...

  9. Kubernetes HPA 的三个误区与避坑指南

    01 前言 Aliware 云计算带来的优势之一便是弹性能力,云原生场景下 Kubernetes 提供了水平弹性扩容能力(HPA),让应用可以随着实时指标进行扩/缩.然而 HPA 的实际工作情况可能和 ...

最新文章

  1. ABAP-FI常用BAPI
  2. hbase报错:org.apache.hadoop.hbase.PleaseHoldException: Master is initializing
  3. redhat 安装Rabbitmq
  4. Eclipse系列的隐藏宝藏-2019年版
  5. java容器遍历_高效遍历Java容器详解
  6. linux shell ls -1 列显示文件
  7. 关于学习js的Promise的心得体会
  8. Keli Linux与网络安全(2)——初探Keli
  9. mysql五日均线代码_通达信均线源码,5日通达信均线公式源码
  10. vb2008如何连接mysql_VB如何连接ACCESS数据库详解
  11. python的画图工具有哪些_python实现画图工具
  12. YUV Alpha Blend 推导过程
  13. ir2104s的自举电容_有关IR2104的自举电容和NMOS选择问题.docx
  14. 悠歌“即时”游戏回合文案
  15. 倒车入库- 通过后视镜调整方向盘
  16. 计算机会计期中考试,2017会计从业资格考试《会计电算化》基础阶段备考题
  17. 数据库(笔记)——关系代数以及相关运算
  18. vue关闭eslint代码检测
  19. ## 虚幻四引擎学习——初学者
  20. 备战一年,终于斩获腾讯T3,我坚信成功是可以复制的

热门文章

  1. 苹果“自研”心不死 仍考虑收购英特尔基带业务
  2. 继腾讯后 B站又获阿里投资!加速二次元电商商业化
  3. 2019年新iPhone消息再曝 将会有重大升级!
  4. XXX packages are looking for funding run `npm fund` for details
  5. python ConfigParser模块详解
  6. vue 切换页面没有改变滚动条_VUE建立照片轮播功能
  7. csredis封装_ASP.NET Core 2.0下使用Redis——基于CSRedis实现
  8. 【kafka】kafka 启动 Version `123123` is not a valid version
  9. 【算法】剑指 Offer 24. 反转链表
  10. 【java】Java实现异步调用方法(jdk1.8)