MySQL 查询大偏移量(LIMIT)问题分析

ops/2024/12/27 15:05:51/

      • 大偏移量查询缓慢?
          • LIMIT: 会进行三步操作
        • 性能消耗在哪里了?
          • ORDER 操作
            • 问题 1
          • OFFSET操作
            • 问题 2
          • LIMIT 操作
        • 如何优化?

大偏移量查询缓慢?

示例:(假设age字段有索引)

SELECT * FROM test WHERE age>18 LIMIT 10000000 ,10;

分析MySQL的 LIMIT 10000000 , 10

LIMIT: 会进行三步操作
  1. ORDER: 排序
  2. OFFSET:跳过多少行数据
  3. LIMIT: 取多少行数据
性能消耗在哪里了?

我们针对三部操作看性能消耗在哪里了

ORDER 操作

MySQL 返回的数据排序方式只有两种:

  1. 默认(不设置排序字段):使用主键进行排序
  2. 指定: 指定排序字段.(示例:ORDER age DESC)
问题 1

如果你的条件where字段与排序order字段不一样,就会回表查询 order字段再用 order 字段排序

所以

SELECT * FROM test WHERE age>18 LIMIT 10000000 ,10

条件字段 age,排序字段主键id(默认)

  1. 会先扫描 age 的索引拿到 age>18 的所有主键 id
  2. 将所有(可能有千万条)主键 id回表并排序(性能消耗巨大)
OFFSET操作

OFFSET是跳过多少行数据,
例子:
比如 OFFSET 10000000并不是直接从 10000001 开始计数,
而是整整要从第1个扫描到 10000001 个数据,然后开始计数)

注意区别
ORDER id OFFSET 10000000 是跳过 id 的前面的10000000 条数据从 10000001条开始,需要扫描到 10000001 条
WHERE id >10000000: 是直接定位到 id=10000000 的数据取大于它的数据

问题 2

所以 OFFSET 越大,需要扫码的数据行数越多,消耗越大.

LIMIT 操作

LIMIT 10 操作本身是没太大消耗的,就是查询数据的时候只取多少条数据(这里是取 10 条),主要是前面的ORDER回表与OFFSET行数跨越的消耗.

如何优化?

主要有两条路线:

  1. 减少不必要的回表(ORDER字段与where字段相同)
    示例:
SELECT * FROM test WHERE age>18 ORDER BY age LIMIT 10000000 ,10;

解释:
1. 走 age 的索引,取出根据 age 排序的第 10000001 到 10000010 条数据的主键
2. 根据主键(10 个)回表查询数据

  • 或者使用覆盖索引(子查询)去避免回表(查询的字段包含在索引中就不用回表)
    建立一个(id,age)的索引
SELECT * FROM test a join (select id from test where age > 18 limit 10000000, 10) b on a.id=b.id;
  1. 尽量不要使用 OFFSET 大偏移量查询,而是使用 where 快速定位.
SELECT * FROM test WHERE age>18 AND id>10000000 LIMIT 10;

参考:
https://juejin.cn/post/7270800456862466087
https://www.51cto.com/article/683765.html
https://blog.csdn.net/hellokitty_nba/article/details/123824417
https://juejin.cn/post/7094807113364406309


http://www.ppmy.cn/ops/145410.html

相关文章

老旧小区用电安全保护装置#限流式防火保护器参数介绍#

摘要 随着居民住宅区用电负荷的增加,用电安全问题日益突出,火灾隐患频繁发生。防火限流式保护器作为一种新型电气安全设备,能够有效预防因电气故障引发的火灾事故。本文介绍了防火限流式保护器的工作原理、技术特点及其在居民住宅区用电系统…

C语言从入门到放弃教程

C语言从入门到放弃 1. 介绍1.1 特点1.2 历史与发展1.3 应用领域 2. 安装2.1 编译器安装2.2 编辑器安装 3. 第一个程序1. 包含头文件2. 主函数定义3. 打印语句4. 返回值 4. 基础语法4.1 注释4.1.1 单行注释4.1.2 多行注释 4.2 关键字4.2.1 C语言标准4.2.2 C89/C90关键字&#xf…

“declarative data-parallel operators“与“MapReduce”

Declarative data-parallel operators “Declarative data-parallel operators”(声明性数据并行操作符)是一种编程范式,它允许程序员以声明性的方式指定数据并行操作,而无需明确指定操作的执行顺序或方式。这种范式旨在简化并行…

kafka的配置

server.properties server.properties模板 # broker id,多个broker服务器的话,每个broker id必须不同 broker.id1# kafka broker所在节点的 hostnamehostname10.1.1.1.3:9092# 处理网络请求的线程数 num.network.threads 8# 执行磁盘IO的线程数 num.io…

经历三次的运放笔试题

简述电阻电容的作用,计算放大倍数 上图假设同向端直接接地:就是最基本的反向放大电路,就像下面这样 R1:输入电阻,R4:反馈电阻,构成反向放大电路,A = VinRf/R= -20k / 10k = -2Vin ;没问题 但是加上R2、R3后,相当于同向输入端也加了输入。此时可以利用叠加定理,也就是…

基于springboot的海洋知识服务平台的设计与实现

基于springboot的海洋知识服务平台的设计与实现 写在前面 需要源码加lzlv58787 开发内容 编程语言:Java / Vue2 框架: SpringBoot Shiro Mybatis-plus 项目结构 后端管理系统前台Web 后端管理系统 前台Web

day17-18-进程管理和系统资源管理

linux资源管理器 linux中对需要运维去管理、去查看的资源信息,如下 内存资源、使用率 free命令磁盘资源、使用率 dfCPU资源、使用率 tophtopglances进程资源、使用率 pspstreepidof网络资源、使用率 Iftop所有资源的整体查看命令 topglanceshtop 一、什么是进程 …

Golang微服务-protobuf

protobuf gRPC是一款语言中立、平台中立、开源的远程过程调用系统,gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用 数据在进行网络传输的时候,需要进行序列化,序列化…