Mysql排序的特性详情
对于一个数据库开发者来说,牢固扎实的基础是十分重要的,golang学习网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《Mysql排序的特性详情》,主要介绍了特性、MySQL排序,希望对大家的知识积累有所帮助,快点收藏起来吧,否则需要时就找不到了!
1、问题场景
新上线一个交易记录导出功能,逻辑很简单:根据查询条件,导出对应的数据。由于数据量比较大,在查询数据库时采用了分页查询,每次查询1000条数据。
自测正常,测试环境正常,上线之后运营反馈导出的数据有重复记录。
原本是以为业务逻辑问题,重新Review了一遍代码,依旧未找到问题原因。最后只好把SQL语句拿出来单独执行,导出数据,对比发现竟然是SQL语句查询结果乱序导致的。
2、原因分析
查询语句以create_time进行倒序排序,通过limit进行分页,在正常情况下不会出现问题。但当业务并发量比较大,导致create_time存在大量相同值时,再基于limit进行分页,就会出现乱序问题。
出现的场景是:以create_time排序,当create_time存在相同值,通过limit分页,导致分页数据乱序。
比如,查询1000条数据,其中有一批create_time记录值都为”2021-10-28 12:12:12“,当创建时间相同的这些数据,一部分出现在第一页,一部分出现在第二页,在查询第二页的数据时,可能会出现第一页已经查过的数据。
也就是说,数据会来回跳动,一会儿出现在第一页,一会儿出现在第二页,这就导致导出的数据一部分重复,一部分缺失。
查看了Mysql 5.7和8.0的官方文档,描述如下:
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对列进行排序时,如果对应(ORDER BY的列)列存在多行相同数据,(Mysql)服务器会按照任意顺序返回这些行,并且可能会根据整体执行计划以不同的方式返回。
简单来说就是:ORDER BY查询的数据,如果ORDER BY列存在多行相同数据,Mysql会随机返回。这就会导致虽然使用了排序,但也会发生乱序的状况。
3、解决方案
针对上述问题,基本的解决思路是:避免ORDER BY列的值出现重复。因此,可以加入其他维度,比如ID等其他排序列。
select * from tb_order order by create_time ,id desc;
这样,在create_time相同时,会根据id进行排序,而id肯定是不同的,就再不会出现上述问题了。
4、拓展知识
其实,上述内容在Mysql的官网已经有明确说明,而且还举了例子。下面对官网的内容和例子做一个简单的汇总总结。
4.1 limit查询优化
如果我们只是查询一个结果集的一部分,那么不要查询所有数据,然后再丢弃不需要的数据,而是要通过limit条件来进行限制。
在没使用having条件时,Mysql可能会对limit条件优化:
- 如果只查询几条数据,建议使用
limit,这样Mysql可能会用到索引,而通常情况下Mysql是全表扫描; - 如果将
limit row_count和order by结合使用,Mysql会在找到第一个row_count结果集后立刻停止排序,而不是对整个结果集进行排序。如果此时基于索引进行操作,速度会更快。如果必须进行文件排序,在找到row_count结果集之前,会对部分或所有符合条件的结果进行排序。但当找到row_count结果之后,便不会对剩余部分进行排序了。这种特性的一个表现就是我们前面提到的带有limit和不带limit进行查询时,返回的结果顺序可能不同。 - 如果将
limit row_count和distinct结合使用,Mysql会在找到row_count结果集唯一行后立马停止。 - 在某些情况下,可以通过按照顺序读取索引(或对索引进行排序),然后计算摘要直到索引变化来实现group by。在这种情况下,
limit row_count不会计算任何不必要的group by值。 - 一旦MySQL向客户端发送了所需数量的行,就会中止查询,除非使用了
SQL_CALC_FOUND_ROWS。在这种情况下,可以使用SELECT FOUND_ROWS()检索行数。 - LIMIT 0会快速返回一个空集合,通常可用于检查SQL的有效性。还可以用于在应用程序中获得结果集的类型。在Mysql客户端中,可以使用
--column-type-info来显示结果列类型。 - 如果使用临时表来解析查询,
Mysql会使用limit row_count来计算需要多少空间。 - 如果
order by未使用索引,且存在limit条件,则优化器可能会避免使用合并文件,而采用内存filesort操作对内存中的行进行排序。
了解了limit的一些特性,下面再回到本文的重点,limit row_count和order by结合使用特性。
4.2 limit与order by结合使用
在上面第二条中已经提到,limit row_count和order by结合呈现的特性之一就是结果返回的顺序是不确定的。而影响执行计划的一个因素就是limit,因此带有limit与不带有limit执行同样的查询语句,返回结果的顺序可能不同。
下面示例中,根据category列进行排序查询,而id和rating是不确定的:
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 | +----+----------+--------+
当查询语句包含limit时,可能会影响到category值相同的数据:
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 | +----+----------+--------+
其中id为3和4的结果位置发生了变化。
在实践中,保持查询结果的顺序性往往非常重要,此时就需要引入其他列来保证结果的顺序性了。
当上述实例引入id之后,查询语句及结果如下:
mysql> SELECT * FROM ratings ORDER BY category, id; +----+----------+--------+ | 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, id LIMIT 5; +----+----------+--------+ | id | category | rating | +----+----------+--------+ | 1 | 1 | 4.5 | | 5 | 1 | 3.2 | | 3 | 2 | 3.7 | | 4 | 2 | 3.5 | | 6 | 2 | 3.5 | +----+----------+--------+
可以看出,当添加了id列的排序,即使category相同,也不会出现乱序问题。这正与我们最初的解决方案一致。
5、小结
本来通过实践中偶发的一个坑,聊到了Mysql对limit查询语句的优化,同时提供了解决方案,即满足了业务需求,又避免了业务逻辑的错误。
很多朋友都在使用order by和limit语句进行查询,但如果不知道Mysql的这些优化特性,很可能已经入坑,只不过数据量没有触发呈现而已。
到这里,我们也就讲完了《Mysql排序的特性详情》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于mysql的知识点!
SpringBoot连接MySQL获取数据写后端接口的操作方法
- 上一篇
- SpringBoot连接MySQL获取数据写后端接口的操作方法
- 下一篇
- MySQL分区表实现按月份归类
-
- 数据库 · MySQL | 1天前 |
- MySQL数值函数大全及使用技巧
- 117浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- 三种登录MySQL方法详解
- 411浏览 收藏
-
- 数据库 · MySQL | 3天前 |
- MySQL数据备份方法与工具推荐
- 420浏览 收藏
-
- 数据库 · MySQL | 3天前 |
- MySQL数据备份方法与工具推荐
- 264浏览 收藏
-
- 数据库 · MySQL | 4天前 |
- MySQL索引的作用是什么?
- 266浏览 收藏
-
- 数据库 · MySQL | 5天前 |
- MySQL排序原理与实战应用
- 392浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQLwhere条件查询技巧
- 333浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL常用数据类型有哪些?怎么选更合适?
- 234浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL常用命令大全管理员必学30条
- 448浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL高效批量插入数据方法大全
- 416浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL性能优化技巧大全
- 225浏览 收藏
-
- 数据库 · MySQL | 1星期前 |
- MySQL数据备份4种方法保障安全
- 145浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- ChatExcel酷表
- ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
- 3164次使用
-
- Any绘本
- 探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
- 3376次使用
-
- 可赞AI
- 可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
- 3405次使用
-
- 星月写作
- 星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
- 4509次使用
-
- MagicLight
- MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
- 3785次使用
-
- Golang中Interface接口的三个特性
- 2023-01-07 394浏览
-
- GoGORM版本2.0新特性介绍
- 2022-12-25 251浏览
-
- Go语言区别于其他语言的特性
- 2022-12-24 108浏览
-
- Golang与其他语言不同的九个特性
- 2023-01-07 425浏览
-
- MySQL关系型数据库事务的ACID特性与实现
- 2023-01-07 408浏览

