作者:猿码道http://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值处理。

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

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

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

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

    点击上方"Java知音",选择"置顶公众号" 技术文章第一时间送达! 作者:猿码道 www.jianshu.com/p/544c319fd838 0 问题描述 ...

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

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

  4. FlyFish|前端数据可视化开发避坑指南(二)

    FlyFish是云智慧开源的一款数据可视化编排平台.通过配置数据模型为用户提供上百种可视化图形组件,零编码即可实现符合自己业务需求的炫酷可视化大屏. 同时,FlyFish也提供了灵活的拓展能力,支持组 ...

  5. python 扒数据_不踩坑的Python爬虫:如何在一个月内学会爬取大规模数据

    Python爬虫为什么受欢迎 如果你仔细观察,就不难发现,懂爬虫.学习爬虫的人越来越多,一方面,互联网可以获取的数据越来越多,另一方面,像 Python这样的编程语言提供越来越多的优秀工具,让爬虫变得 ...

  6. mysql 查找相似数据_跳槽必备:MySQL高频面试题,都在这了!

    前言 本文主要受众为开发人员,所以不涉及到MySQL的服务部署等操作,且内容较多,大家准备好耐心和瓜子矿泉水. 前一阵系统的学习了一下MySQL,也有一些实际操作经验,偶然看到一篇和MySQL相关的面 ...

  7. mysql8导入 psc 没有数据_新特性解读 | MySQL 8.0.22 任意格式数据导入

    作者:杨涛涛 资深数据库专家,专研 MySQL 十余年.擅长 MySQL.PostgreSQL.MongoDB 等开源数据库相关的备份恢复.SQL 调优.监控运维.高可用架构设计等.目前任职于爱可生, ...

  8. 怎么把原来的墙拆掉_电视墙避坑指南要收好!拆掉重装太心累...

    电视墙是家里装修最为重要的一个地方. 相信很多人都想要把电视墙装修得简单又大气,而且还是容易搞卫生的整洁类型~但是,电视墙贴砖过程中,有很多坑需要注意,一不小心就要像下面的业主一样,拆掉重装. 业主反 ...

  9. python向mysql中添加数据_通过python操控MYSQL添加数据,并将数据添加到EXCEL中-阿里云开发者社区...

    第一步 在python中创建mysql数据表 import pymysql #导入模块 def getCon(): #联接到数据库,并封装循环使用,db是数据库名字 conn = pymysql.co ...

最新文章

  1. 浙江大学 | 深度域自适应和小目标检测挑战、技术和数据集:调研
  2. Java的新项目学成在线笔记-day12(九)
  3. SAP数据表(一)商品表
  4. dapper使用时性能优化
  5. Provisional headers are shown in Chrome network tab
  6. python读取写入文件_Python文件读写保存操作
  7. 领域应用 | 基于知识图谱的警用安保机器人大数据分析技术研究
  8. win固定ip无效,自动配成169.254.xx.xx
  9. TCP压测工具 终极 全新版
  10. 两相四线混合式步进电机用双H桥驱动电路之Multisim仿真及优化
  11. Visual Studio 2013安装教程
  12. 软件测试面试经常会被问到的三大问题(面试常考)
  13. 提示网站服务器403,浏览器打开网页时出现http 403 禁止访问错误是什么原因?
  14. HTML英雄联盟 效果图代码结构 (多多指教,感谢)
  15. F1赛车相关公开数据集
  16. Stochastic Depth ResNet
  17. Java远程调用BPS流程实现流程运行简单示例
  18. 2021年前的最后一篇文章,分享一下前端这几年的感受和心得,总结过去展望未来
  19. session 超时时间设置
  20. 程序员月薪2万是什么水平,砥砺前行!

热门文章

  1. 例子---JS无缝轮播图
  2. 判断一个字符串是否是回文_Python
  3. android数据库开发案例教程,Android Studio项目开发教程 第6章 数据库编程(30页)-原创力文档...
  4. python export_django-import-export插件使用教程
  5. rsa前后端加密流程_不懂前后端分离?这篇就够了
  6. java cygwin,cygwin和java
  7. java后端站内通知_正确使用Java事件通知
  8. python测验2_测验2: Python基础语法(上) (第4周)
  9. 自动化C语言第一次月考试卷,计算机专业第一次月考.doc
  10. php mysql密码验证_php 连接数据库 验证用户名密码