栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

MySql limit和order by一起使用出现的分页重复数据Bug

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

MySql limit和order by一起使用出现的分页重复数据Bug

 閭博主介绍:小黄鸭技术

擅长领域:Java、实用工具、运维

 系列专栏:Bug之路

如果文章写作时有错误的地方,请各位大佬指正,一起进步!!!

李欢迎大家点赞➕收藏⭐➕评论支持博主爛  

项目场景

项目中有一个接口返回全量数据,数据量比较大导致页面渲染缓慢,所以改成分页来提高响应速度,按照一个状态status来排序。


问题描述

本来以为利用PageHelper加一下分页,语句中加上 order by status 就ok了,结果实际使用时发现分页中有重复数据。

Java代码示例:

// 设置分页
PageHelper.startPage(param.getCurrentPage(), param.getPageSize());
List list = userMapper.selectByPage(user.getClassId());

Mapper示例:

SELECT
	* 
FROM
	user_info 
WHERe
	STATUS = 0 
	AND class_id = '1' 
ORDER BY
STATUS 
	LIMIT 10

原因分析

因为status字段有重复,只是0和1。

原理分析

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

使用priority queue目的

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

  • 因为 priority queue 使用了堆排序的排序方法,而堆排序是一个不稳定的排序方法,也就是相同的值可能排序出来的结果和读出来的数据顺序不一致。
  • MySQL 5.5版本没有优化,所以不会产生此问题

解决方案 索引字段排序

对排序字段加上索引,利用索引的有序性来解决此问题

再添加一个不会重复的字段来做联合排序

当出现重复时,按照第二个字段排序。

SELECt
	* 
FROM
	user_info 
WHERe
	STATUS = 0 
	AND class_id = '1' 
ORDER BY
STATUS,id 
	LIMIT 10

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/931138.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号