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

具体如下:

SELECT `post_title`,`post_date` FROM post WHERE `post_status`='publish' ORDER BY view_count desc LIMIT 5,5

使用上述SQL查询的时候,很有可能出现和LIMIT 0,5相同的某条记录,而如果使用:

SELECT * FROM post WHERE post_status='publish' ORDER BY view_count desc LIMIT 5,5
则不会出现重复的情况。但是,由于post表的字段很多,我仅仅希望用这两个字段,不想把post_content也查出来。为了解决这个情况,我在ORDER BY后面使用了两个排序条件来解决这个问题。

SELECT `post_title`,`post_date` FROM post WHERE `post_status`='publish' ORDER BY view_count desc,ID asc LIMIT 5,5

按理来说,mysql的排序默认情况下是以主键ID作为排序条件的,也就是说,如果在view_count相等的情况下,主键ID作为默认的排序条件,不需要我们多此一举加ID asc。但是事实就是,mysql再order by和limit混用的时候,出现了排序的混乱情况。其后的机理我尚不得而知,在阅读这篇文章后,好像有所领悟,下面做一下猜测。

这篇文章的解释是:

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

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

之所以5.6出现了第二页数据重复的问题,是因为 priority queue
使用了堆排序的排序方法,而堆排序是一个不稳定的排序方法,也就是相同的值可能排序出来的结果和读出来的数据顺序不一致。

5.5 没有这个优化,所以也就不会出现这个问题。

也就是说,mysql5.5是不存在本文提到的问题的,5.6版本之后才出现了这种情况。

我们再看下mysql解释sql语言时的执行顺序:

(7)     SELECT
(8) DISTINCT <select_list>
(1) FROM <left_table>
(3) <join_type> JOIN <right_table>
(2) ON <join_condition>
(4) WHERE <where_condition>
(5) GROUP BY <group_by_list>
(6) HAVING <having_condition>
(9) ORDER BY <order_by_condition>
(10) LIMIT <limit_number>

在我们本文的案例sql中,执行顺序依次为form… where… select… order by… limit…

由于上述priority queue的原因,在完成select之后,所有记录是以堆排序的方法排列的,在进行order by时,仅把view_count值大的往前移动。但由于limit的因素,排序过程中只需要保留到5条记录即可,view_count并不具备索引有序性,所以当第二页数据要展示时,mysql见到哪一条就拿哪一条,因此,当排序值相同的时候,第一次排序是随意排的,第二次再执行该sql的时候,其结果应该和第一次结果一样。

这只是我的猜测,有理解的朋友,请帮忙解答。

mysql orderby limit 翻页数据重复的问题的更多相关文章

  1. postgresql-分页数据重复问题探索

    postgresql-分页数据重复探索 问题背景 许多开发和测试人员都可能遇到过列表的数据翻下一页的时候显示了上一页的数据,也就是翻页会有重复的数据. 如何处理? 这个问题出现的原因是因为选择的排序字 ...

  2. 为什么MYSQL分页时使用limit+ order by会出现数据重复问题

    问题描述: MYSQL采用limit进行翻页查询时,搭配order by ,在翻到第二页的时候可能会出现第一页的数据,  示例sql如下: select  a,b from c where d = ' ...

  3. ASP NET Core --- HTTP 翻页、过滤、排序

    参照 草根专栏- ASP.NET Core + Ng6 实战:https://v.qq.com/x/page/v07647j3zkq.html 翻页, 过滤, 排序等 – 如何传递参数? Query ...

  4. Atitit.列表页面and条件查询的实现最佳实践(2)------翻页 分页 控件的实现java .net php

    )------翻页 分页 控件的实现java .net php 1. 关于翻页有关的几大控件::搜索框控件,显示表格控件,翻页器,数据源控件.. 1 2. 翻页的显示格式:: 1 2.1. 通常ui- ...

  5. mysql实战优化之二:limit优化(大表翻页查询时) sql优化

    mysql的表test中有20105119行数据.建立索引:data_status,place_cargo_status 场景1: SELECT id, resource_id, resource_t ...

  6. 最快速的办法解决MySQL数据量增大之后翻页慢问题

    MySQL最易碰到的性能问题就是数据量逐步增大之后的翻页速度变慢的额问题,而且越往后翻页速度越慢,如果用最快速的办法解决,以下就是解决办法,简单方便. 1.问题现状 现有MySQL数据表 event_ ...

  7. MySQL翻页查询技巧

    在查询大量数据库,一般都会采用翻页.自然会想到offset跟limit. 今天知道了一个技巧,用id查询.因为id是主键,查起来很快. 思路是:给id一个区间做where条件,将数据分隔成几份,然后每 ...

  8. JeeSite数据分页与翻页

    本文章介绍的是JeeSite开源项目二次开发时的一些笔记,对于没有使用过JeeSite的可以不用往下看了,因为下面的代码是跟JeeSite二次开发相关的代码,不做JeeSite的二次开发,以下代码对您 ...

  9. 37.scrapy解决翻页及采集杭州造价网站材料数据

    1.目标采集地址: http://183.129.219.195:8081/bs/hzzjb/web/list 2.这里的翻页还是较为简单的,只要模拟post请求发送data包含关键参数就能获取下一页 ...

随机推荐

  1. StackOverflow经典问题:代码中如何去掉烦人的“!=null"判空语句

    问题 为了避免空指针调用,我们经常会看到这样的语句 if (someobject != null) { someobject.doCalc();} 最终,项目中会存在大量判空代码,多么丑陋繁冗!如何避 ...

  2. 让Github畅通无阻,FastGithub1.0.0发布

    前言 我近半年来被github的抽风虐得没脾气了,虽然我有代理的方式来上网,但代理速度并不理想,而且有时代理服务一起跟着抽风.这时候,我会搜索"github访问不了"相关题材,其中 ...

  3. NOIP模拟测试30「return·one·magic」

    magic 题解 首先原式指数肯定会爆$long$ $long$ 首先根据欧拉定理我们可以将原式换成$N^{\sum\limits_{i=1}^{i<=N} [gcd(i,N)==1] C_{G ...

  4. VsCode中代码折叠快捷键

    ctrl+K  ctrl+[  折叠本级 ctrl+K  ctrl+]  取消折叠本级 ctrl+K  ctrl+0  折叠全部 ctrl+K  ctrl+J  取消折叠全部

  5. WEB安全新玩法 [5] 防范水平越权之查看他人订单信息

    水平越权是指系统中的用户在未经授权的情况下,查看到另一个同级别用户所拥有的资源.水平越权会导致信息泄露,其产生原因是软件业务设计或编码上的缺陷.iFlow 业务安全加固平台可以缓解部分场景下的水平越权 ...

  6. cURL命令使用指南

    cURL是什么 curl是Linux命令行工具,可以使用任何可支持的协议(如HTTP.FTP.IMAP.POP3.SCP.SFTP.SMTP.TFTP.TELNET.LDAP或FILE)在服务器之间传 ...

  7. 非静态的字段、方法或属性“System.Web.UI.Page.ClientScript.get”要求对象引用

    解决Response.Write("<script>alert('修改失败,请稍后再试!');</script>");布局错误的问题 在后台CS代码(不是C ...

  8. centos 8 sonarqube 设置开机自启动解决方案

    编写开机自启动脚本 进入到开机自启动调用文件目录 vim /etc/systemd/system/sonarqube.service [Unit] Description=SonarQube serv ...

  9. Centos6.7 minimal安装GitLab8.3.4配置LDAP、发邮件以及升级到GitLab8.5.4

    建议使用非root账户安装,先同步系统时间: ntpdate cn.pool.ntp.org 1.创建用户gitlab 注意:centos下,adduser和useradd的命令效果是一样的,但ubu ...

  10. Docker:Linux离线安装docker-17.03.2-ce,配置开机自启

    1. 准备docker离线包 docker官方离线包下载地址 下载需要安装的docker版本,我此次下载的是:docker-17.03.2-ce.tgz 2. 准备docker.service 系统配 ...