MySQL 系列:注意 ORDER 和 LIMIT 联合使用的陷阱

文章目录

  • 前言
  • 背后的原因
    • ORDER BY 排序列存在相同值时返回顺序是不固定的
    • LIMIT 和 ORDER BY 联合使用时的行为
    • ORDER BY 或 GROUP BY 和 LIMIT 联合使用优化器默认使用有序索引
  • 如何解决
  • 其它说明
  • 个人简介

前言

  • 不知道大家在在分页查询中有没有遇到过这个问题,分页查询中不同的页中出现了同一条数据,出现了分页错乱的问题:

查询数据源

  • 整体排序:SELECT * from test_1 ORDER BY create_date;

整体排序

  • 提取排序后的前两条:SELECT * from test_1 ORDER BY create_date LIMIT 0,2;

LIMIT 0,2

  • 提取排序后的最后两条:SELECT * from test_1 ORDER BY create_date LIMIT 8,2;

LIMIT 8,2

  • 上面的结果是不是很奇怪,按照大家正常的思考,MySQL 对我们查询的数据进行整体排序,我们按页取出,理论上不应该在不同的页中有相同的数据,下面我们一起来看看隐藏在背后的原因。

背后的原因

  • https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
  • 官网的说明内容比较多,我主要摘抄了以下几点比较相关的内容,下面我们一起来看看吧。

ORDER BY 排序列存在相同值时返回顺序是不固定的

  • If multiple rows have identical values in the ORDER BY columns, the server is free to return those rows in any order, and may do so differently depending on the overall execution plan. In other words, the sort order of those rows is nondeterministic with respect to the nonordered columns.
  • 如果多个行在ORDER BY列中具有相同的值,则服务器可以自由地以任何顺序返回这些行,并且可以根据总体执行计划以不同的方式返回。换句话说,相对于无序列,这些行的排序顺序是不确定的。

LIMIT 和 ORDER BY 联合使用时的行为

  • If you combine LIMIT row_count with ORDER BY, MySQL stops sorting as soon as it has found the first row_count rows of the sorted result, rather than sorting the entire result. If ordering is done by using an index, this is very fast. If a filesort must be done, all rows that match the query without the LIMIT clause are selected, and most or all of them are sorted, before the first row_count are found. After the initial rows have been found, MySQL does not sort any remainder of the result set.
  • 如果你联合使用 LIMIT 和 ORDER BY ,MySQL 会找到所需要的行后尽可能快的返回,而不是对所有满足查询条件的行进行排序。如果使用索引排序,那么速度会非常快;如果使用文件排序,所有满足条件都会被选中(不包括 Limit 条件),这些行的大多数,或全部都会被排序直到满足 Limit 的行数。满足的行数一旦找到,则不会对剩余的数据进行排序。
  • 我们看一下官网的例子:
// 全表排序时
mysql> SELECT * FROM ratings ORDER BY category;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
|  1 |        1 |    4.5 |
|  5 |        1 |    3.2 |
|  3 |        2 |    3.7 |
|  4 |        2 |    3.5 |
|  6 |        2 |    3.5 |
|  2 |        3 |    5.0 |
|  7 |        3 |    2.7 |
+----+----------+--------+// 部分排序时
mysql> SELECT * FROM ratings ORDER BY category LIMIT 5;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
|  1 |        1 |    4.5 |
|  5 |        1 |    3.2 |
|  4 |        2 |    3.5 |
|  3 |        2 |    3.7 |
|  6 |        2 |    3.5 |
+----+----------+--------+// 可以看到 MySQL 并没有对所有数据整体排序之后再取数据

ORDER BY 或 GROUP BY 和 LIMIT 联合使用优化器默认使用有序索引

  • For a query with an ORDER BY or GROUP BY and a LIMIT clause, the optimizer tries to choose an ordered index by default when it appears doing so would speed up query execution. Prior to MySQL 5.7.33, there was no way to override this behavior, even in cases where using some other optimization might be faster. Beginning with MySQL 5.7.33, it is possible to turn off this optimization by setting the optimizer_switch system variable's prefer_ordering_index flag to off.
  • 简单来说,5.7.33 以前会默认会选择排序字段的索引,即使存在更快的查询计划;5.7.33 开始我们可以关闭这种优化行为。我们来看一下官网提供的例子:
mysql> CREATE TABLE t (->     id1 BIGINT NOT NULL,->     id2 BIGINT NOT NULL,->     c1 VARCHAR(50) NOT NULL,->     c2 VARCHAR(50) NOT NULL,->  PRIMARY KEY (id1),->  INDEX i (id2, c1)-> );// prefer_ordering_index 开启(默认开启)
mysql> SELECT @@optimizer_switch LIKE '%prefer_ordering_index=on%';
+------------------------------------------------------+
| @@optimizer_switch LIKE '%prefer_ordering_index=on%' |
+------------------------------------------------------+
|                                                    1 |
+------------------------------------------------------+mysql> EXPLAIN SELECT c2 FROM t->     WHERE id2 > 3->     ORDER BY id1 ASC LIMIT 2\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: tpartitions: NULLtype: index
possible_keys: ikey: PRIMARYkey_len: 8ref: NULLrows: 2filtered: 70.00Extra: Using where// prefer_ordering_index 关闭
mysql> SET optimizer_switch = "prefer_ordering_index=off";
mysql> EXPLAIN SELECT c2 FROM t->     WHERE id2 > 3->     ORDER BY id1 ASC LIMIT 2\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: tpartitions: NULLtype: range
possible_keys: ikey: ikey_len: 8ref: NULLrows: 14filtered: 100.00Extra: Using index condition; Using filesort

如何解决

  • 从上面我们可以知道,ORDER 列存在相同字段返回的顺序是不确定,且 LIMIT 和 ORDER BY 联合使用时可能不会对所有行进行排序,我们可以在排序字段中加入一个不存在重复值的列进行辅助排序,那么则不会存在这个问题。
  • 比如在文章开头的案例中我们可以加入 ID 字段进行辅助排序:
  • SELECT * from test_1 ORDER BY create_date,id;

ORDER BY create_date,id

  • SELECT * from test_1 ORDER BY create_date,id LIMIT 0,2;

ORDER BY create_date,id LIMIT 0,2

  • SELECT * from test_1 ORDER BY create_date,id LIMIT 8,2;

ORDER BY create_date,id LIMIT 8,2

  • 可以看到,分页的顺序和我们整体排序的顺序一致,不会出现分页错乱的问题。

其它说明

  • MySQL 版本:
SELECT VERSION();5.7.36-log

个人简介

👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.

🚀 我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。

🧠 作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。

💡 在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。

🌐 我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。

📖 保持关注我的博客,让我们共同追求技术卓越。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/219791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据通信网络基础

数据通信网络基础(1) 一.前言 • 在人类社会的起源和发展过程中,通信就一直伴随着我们。从20世纪七、八十年代开始, 人类社会已进入到信息时代,对于生活在信息时代的我们,通信的必要性更是不言而喻 的。…

使用Python监控服务器在线状态

前言 在公司内网有一台服务器,有动态的公网IP,使用DDNS对外提供服务,但是会因为停电、服务器卡死等原因导致服务器离线。服务器离线后无法及时获知,因此需要实现在服务器离线的时候能够发送消息到手机上。 思路梳理 公司办理的…

使用meta的audiobox生成广播剧

在gpt中生成对话: 生成一段一个小男孩和一个小女孩,在森林中并肩走在林间小路上的谈话,请用英文,并配有林中各种声效, 在gpt中生成男孩的声音描述 请用英文描述一下小男孩的声音特点 在gpt中生成女孩的声音描述 请用英…

基于单片机的电梯声控系统设计(论文+源码)

1.系统设计 在目前的高楼住宅,商业大厦中电梯是不可或缺的,而传统的电梯控制器系统,通常需要用户用手去按下按键进行控制,但是这种方式在有些情况下,并不完善,比如在本次新冠疫情期间,由于新冠…

甲醛酒精氢气浓度检测MP503传感器模块设计原理说明

模块简介: 本模块采集MP503空气质量传感器信号,通过单片机的10位ADC对传感器信号采样,并通过气体浓度线性曲线算法计算出气体浓度,可计算出甲醛、酒精、氢气浓度值。模块以TTL串口作为数据输出接口。 2.技术指标: 产品型号 KM-MP503 检测对象 甲醛、酒精、氢气浓度 通信…

设计模式(2)--对象创建(4)--原型

1. 意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 2. 两种角色 抽象原型(Prototype)、具体原型(Concrete Prototype) 3. 优点 3.1 对客户隐藏了具体的产品类 3.2 可以在运行时刻增加和删除产品 3.3 可以极大地减少系统所需要的类的数目 …

OpenStack网络详解

本文主要解释了OpenStack在安装完毕——创建网段与dhcp——创建虚拟机的过程中,系统中多出来的这一堆网卡到底分别连接哪两部分的网卡,以及哪些设备是虚拟出来的。 拓扑 红色代表ovs与网桥 蓝色代表命名空间或者虚机 绿色代表网卡 网络概况 openstack安…

大语言模型--能力

能力 大语言模型 能力从语言模型到任务模型的转化语言建模总结 从语言模型到任务模型的转化 在自然语言处理的世界中,语言模型 p p p是一种对代币序列 x 1 : L x_{1:L} x1:L​这样的模型能够用于评估序列,例如 p ( t h e , m o u s e , a t e , t h e ,…

java设计模式学习之【享元模式】

文章目录 引言享元模式简介定义与用途实现方式 使用场景优势与劣势在Java中的应用享元模式在Spring中的应用画图示例代码地址 引言 想象一下,您正在开发一个游戏,游戏中有成千上万的树木和建筑。如果每个对象都独立存储它的所有数据,将会占用…

(开源)2023工训大赛智能垃圾分类项目(可循环播放视频,显示垃圾分类信息,拍照识别,垃圾分类,满载报警,压缩)

省赛:由于这个比赛是两年一届,并未做足充分的准备,但是通过一定的单片机基础,加上速成能力,也就是熬夜学,通过疯狂的网络搜索,在省赛第5 入选国赛 下面来简单介绍一下我们作品: 主控&#xff1…

总结一些vue3小知识2

1.el-tree-select和el-tree组件报错(有的下拉选项选择不了,一点击就报错,但是有的却能选择,不会报错) 原因:就如同v-for一样,需要添加key才不会出现渲染错误,而el-tree-select和el-tree组件需要…

Sketch for Mac:实现你的创意绘图梦想的矢量绘图软件

随着数字时代的到来,矢量绘图软件成为了广告设计、插画创作和UI设计等领域中必不可少的工具。在众多矢量绘图软件中,Sketch for Mac(矢量绘图软件)以其强大的功能和简洁的界面脱颖而出,成为了众多设计师的首选。 Sket…

用XAMPP在Windows系统构建一个本地Web服务器

用XAMPP在Windows系统构建一个本地Web服务器 Build a Local Web Server for Windows with XAMPP By JacksonML 本文简要介绍如何获取和安装XAMPP以实现Windows环境下本地Web服务器的过程,希望对广大网友和学生有所帮助。 所谓本地Web服务器,即使用本地…

el-date-picker限制选择7天内禁止内框选择

需求&#xff1a;elementPlus时间段选择框需要满足&#xff1a;①最多选7天时间。②不能手动输入。 <el-date-picker v-model"timeArrange" focus"timeEditable" :editable"false" type"datetimerange" range-separator"至&qu…

记录汇川:套接字TCP通信-梯形图

H5U集成一路以太网接口。使用AutoShop可以通过以太网方便、快捷对H5U进行行监控、下载、上载以及调试等操作。同时也可以通过以太网与网络中的其他设备进行数据交互。H5U集成了Modbus-TCP协议&#xff0c;包括服务器与客户端。可轻松实现与支持Modbus-TCP的设备进行通讯与数据交…

django--分页功能

Django 提供了强大的分页功能&#xff0c;可以轻松地在视图中实现分页。 在视图中使用分页&#xff1a; # views.py from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.shortcuts import render from .models import YourModeldef your…

Vue2面试题:说一下组件通信有哪些方式?

父传子 1、自定义属性 props&#xff1a;在父组件中&#xff0c;给子组件绑定一个自定义属性&#xff0c;在子组件中&#xff0c;通过props进行接收 2、$parent&#xff1a;直接访问父组件实例的属性和方法 3、$attrs&#xff1a;在父组件中&#xff0c;给子组件绑定一个自定义…

Hbase的Rowkey设计

Hbase的Rowkey设计 rowkey设计 # 1&#xff09;长度原则# 最大64KB&#xff0c;推荐长度10~100 byte# 最好设为8的倍数&#xff0c;能短则短&#xff0c;rowkey如果太长会影响性能。# 2&#xff09;唯一原则&#xff1a;rowkey应该具备唯一性# 3&#xff09;散列原则…

【Qt QML入门】Image

Image类型显示一个图像。 使用source属性将图像的源指定为URL。图像可以以Qt支持的任何标准图像格式提供&#xff0c;包括位图格式&#xff0c;如PNG和JPEG&#xff0c;以及矢量图形格式&#xff0c;如SVG。 如果没有指定宽度和高度属性&#xff0c;图像将自动使用加载图像的大…

IDEA上传jar包到Maven

mvn install:install-file //固定格式&#xff0c;maven的语法 -Dfilealibaba-sdk-1.0.0.jar //这里填写包的路径&#xff0c;因为我们是在当前目录所以只需要输入包名即可 -DgroupIdcom.qiehua.csdn //这里填写包的groupId&#xff0c;之后作为pom.xml中引用的gr…