网站首页 > 基础教程 正文
现象描述
select * from table order by xx limit 0,10
看似一句没有问题的sql语句,其实它其中也暗藏着一些坑,既当xx不存在索引,且有xx相同的行是,可能出现分页数据重复问题。想当初在做数据迁移任务时,我以add_time(添加时间,该字段为加索引)为排序字段,总是会报DuplicateKeyException,当时很奇怪,通过日志分析发现分页中某一页的结束行,是另一页的开始行,对这种现象甚是纳闷,想为啥会出现这种现象,经过多方努力查找网络,原理分析如下:
原理分析
这段文字来源mysql官网,该段文字的主要意思就是说,如果order by后面的排序字段存在多个相同值得话,那么mysql排序返回的结果解释不稳定的,mysql会随机返回相同行的记录,从而就有可能出现分页重复问题。
网上也有对此作了比较详细的解释,就是:
在MySQL 5.6的版本上,优化器在遇到order by limit语句的时候,做了一个优化,即使用了priority queue。使用 priority queue 的目的,就是在不能使用索引有序性的时候,如果要排序,并且使用了limit n,那么只需要在排序的过程中,保留n条记录即可,这样虽然不能解决所有记录都需要排序的开销,但是只需要 sort buffer 少量的内存就可以完成排序。之所以5.6出现了第二页数据重复的问题,是因为 priority queue 使用了堆排序的排序方法,而堆排序是一个不稳定的排序方法,也就是相同的值可能排序出来的结果和读出来的数据顺序不一致。5.5 没有这个优化,所以也就不会出现这个问题。
不管是官网,还是网上版本的解释,多说明了由于是存在相同行字段作为排序的字段,从而导致mysql返回的结果集不稳定,所以会有可能导致分页重复
解决方案
上面大概意思是说,如果返回相同排序结果在有和没有limit的情况下很重要的话,可以在order by的后面再加上个值唯一的字段,来确保返回结果的稳定性。如下面的操作
让索引字段一同参与排序,假设id为主键,如
select * from table order by xx,id(任意有索引的字段) limit 0,10
附:mysql官网文档地址:https://dev.mysql.com/doc/refman/5.6/en/limit-optimization.html
猜你喜欢
- 2024-10-16 web前端移动端最流行的网页布局技术:flexbox弹性布局学习详解
- 2024-10-16 美团团购订单系统优化记 美团团购订单系统优化记录怎么删
- 2024-10-16 6.8 Apache访问控制 控制用户访问apache目录的配置文件
- 2024-10-16 快速学会html表单提交(php) html提交表单到php
- 2024-10-16 Django开发教程(七) django开发工具
- 2024-10-16 前端配置prettier,eslint ,stylelint
- 2024-10-16 电脑绝技教你22天学精Csharp之第十八天HTML和CSS补充3
- 2024-10-16 HTML部分第四章——HTML常用标签 html标签大全及用法图解
- 2024-10-16 基于Django+mysql的点餐系统设计-第八篇(H5主页调试-静态页面)
- 2024-10-16 什么是 Promise.all 什么是suv汽车
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)