mysql查询的原始返回顺序与limit分页优化

mysql查询时每条记录的原始返回顺序

mysql 查询时每条记录的原始返回顺序,由此sql语句的执行计划和内部存储引擎的实现决定【跟实现细节有关,跟sql语义无关=>不是 接口契约 即在sql语义上来说是未定义的】=>只有查询时加了 order by 后才根据order by字段 升序或者降序返回

即 原始返回顺序,由 MySQL 在该次查询中选择的"访问路径(access path)"决定,而不是 SQL 语义决定。

受执行计划的影响:

如果执行计划是 主键索引扫描:返回顺序 ≈ 主键 B+Tree 的叶子节点顺序【而不是插入到表时顺序】

如果 MySQL 走的是 二级索引:顺序是:二级索引 key 顺序 + 主键值顺序【而不是插入到表时顺序】

如果一条sql语句本身虽然没变,但是执行计划变了,比如索引变动;原始查询(不加order by 的查询)的返回顺序也会变

limit分页查询优化

LIMIT offset, count 在 offset 很大时变慢,是因为 MySQL 必须"先找到并丢弃 offset 行",这些工作量不会因为 LIMIT 而减少。

即mysql必须根据执行计划先找到前offset行 再丢弃;=>跟是否加索引无关,无论是否加索引都是先要找到前offset行 再丢弃 =>LIMIT 只限制返回行数,不限制扫描行数。

优化方案:

1.游标分页

如果能确定offset那一行的某个唯一列的值(比如自增主键ID),可以用 WHERE 子句来代替 OFFSET,从而避免扫描和丢弃大量行。 以及保证查询得到返回顺序结构不变【比如使用order by 前面的那个唯一的列】=>就可以使用 游标分页

SELECT *

FROM t

WHERE id > last_id 【范围查询】

ORDER BY id

LIMIT 20;

游标分页的条件是:只要使用范围查询的键(字段)满足 全序,稳定,可比较,唯一性 即可【不要求该键必须连续自增】=>雪花算法生成的ID 是可以的

2.覆盖索引+回表查询=>通常是在子查询中先使用 覆盖索引查询进行limit分页查询,虽然此时子查询中依然需要扫描offset的条数,但是因为是覆盖索引扫描,扫描效率高很多;然后再通过主键回表查询完整记录=>【即外部的查询通过子查询的结果进行回表查询查询完整数据】

相当于大量的offset扫描是在覆盖索引上进行的,回表查询只查询少量数据

SELECT *

FROM t

WHERE id IN (

SELECT id

FROM t

ORDER BY id

LIMIT 1000000, 20

)

ORDER BY id;

3.不允许用户查询过大的offset,必须通过时间,状态,关键字等条件进行过滤,只查询过滤后的数据减少offset的大小=>相当于一种泛化(模糊)版的游标分页

相关推荐
云贝贝贝38 分钟前
腾讯云 TDSQL(MySQL 版)运维高频 6 坑:代理路由、读写分离、分片键、监控、PITR
运维·mysql·腾讯云
山岚的运维笔记4 小时前
mysql 专业笔记 -- 第 8 章:使用变量
运维·数据库·笔记·后端·学习·mysql·dba
JavaPub-rodert9 小时前
Redis 和 MySQL 如何保证数据一致性?从业务方案到底层原理完整讲解
数据库·redis·mysql
笑梦无境10 小时前
mysql的安装及配置(3)
数据库·mysql·adb
Gent_倪11 小时前
MySQL分库、分表、分区详解
数据库·mysql
Wang's Blog11 小时前
Vibe Coding一人即团队系列54:云服务器 Node.js 与 MySQL 9 环境搭建及配置指南
服务器·人工智能·mysql·node.js
数智启示录11 小时前
Apache Kafka 幂等 Producer 的边界:Exactly-Once 到了 MySQL 为什么失效 【Kafka合集】
数据库·经验分享·分布式·mysql·面试·kafka·apache
—Miss. Z—12 小时前
计算机三级数据库技术—填空题
数据库·mysql
Gent_倪14 小时前
MySQL 与 Hive 语法异同点详解
数据库·hive·mysql
老周聊架构14 小时前
Flink 连接器与生态:Kafka Offset 提交修复与 MySQL Binlog 延迟指标
mysql·flink·kafka