解决深度分页问题

简介: 解决深度分页问题

MySQL__深度分页问题
13/100
发布文章
weixin_69252724
未选择文件

文章目录

😊 @ 作者:Lion J
💖 @ 主页: https://blog.csdn.net/weixin_69252724
🎉 @ 主题: MySQL__深度分页问题)
⏱️ @ 创作时间:2024年04月27日
————————————————

在我一次测试中, 100万条数据, 一次偶然的数据展示中, 发现响应数据特别慢, 从前端到后端的一个问题检查上, 最终我是将问题锁定在了一个SQL语句上面. 也就是导致 深度分页问题的罪魁祸首

# MySQL 在无法利用索引的情况下跳过1000000条记录后,再获取10条记录
SELECT * FROM t_order ORDER BY id LIMIT 1000000, 10

这块有几种的解决方案:

  • 范围查询

    当可以保证 ID 的连续性时,根据 ID 范围进行分页是比较好的解决方案

    # 查询指定 ID 范围的数据
    SELECT * FROM t_order WHERE id > 100000 AND id <= 100010 ORDER BY id
    # 也可以通过记录上次查询结果的最后一条记录的ID进行下一页的查询:
    SELECT * FROM t_order WHERE id > 100000 LIMIT 10
    

    这种优化方式限制比较大,且一般项目的 ID 也没办法保证完全连续, 并且有可能不是通过ID来查找的

  • 子查询

    我们先查询出 limit 第一个参数对应的主键值,再根据这个主键值再去过滤并 limit,这样效率会更快一些。

# 通过子查询来获取 id 的起始值,把 limit 1000000 的条件转移到子查询
SELECT * FROM t_order WHERE id >= (SELECT id FROM t_order limit 1000000, 1) LIMIT 10;

不过 ,子查询的结果会产生一张新表,会影响性能,应该尽量避免大量使用子查询
并且,这种方法只适用于 ID 是正序的。在复杂分页场景,往往需要通过 过滤条件,筛选到符合条件的 ID,此时的 ID 是离散且不连续的。

  • 延迟关联
  1. 延迟关联的优化思路,跟子查询的优化思路其实是一样的: 都是把条件转移到主键索引树,减少回表的次数不同点是,延迟关联使用了 inner join(内连接) 包含子查询。
    SELECT t1.* FROM t_order t1
    INNER JOIN (SELECT id FROM t_order limit 1000000, 10) t2
    ON t1.id = t2.id;
    
  2. 还可以使用逗号连接子查询。
    SELECT t1.* FROM t_order t1,
    (SELECT id FROM t_order limit 1000000, 10) t2
    WHERE t1.id = t2.id;
    
  • 覆盖索引

    索引中已经包含了所有需要获取的字段的查询方式称为覆盖索引。

覆盖索引的好处

  1. 避免 InnoDB 表进行索引的二次查询,也就是回表操作: InnoDB 是以聚集索引的顺序来存储的,对于 InnoDB 来说,二级索引在叶子节点中所保存的是行的主键信息,如果是用二级索引查询数据的话,在查找到相应的键值后,还要通过主键进行二次查询才能获取我们真实所需要的数据。而在覆盖索引中,二级索引的键值中可以获取所有的数据,避免了对主键的二次查询(回表),减少了 IO 操作,提升了查询效率。
  2. 可以把随机 IO 变成顺序 IO 加快查询效率: 由于覆盖索引是按键值的顺序存储的,对于 IO 密集型的范围查找来说,对比随机从磁盘读取每一行的数据 IO 要少的多,因此利用覆盖索引在访问时也可以把磁盘的随机读取的 IO 转变成索引查找的顺序 IO。
    # 如果只需要查询 id, code, type 这三列,可建立 code 和 type 的覆盖索引
    SELECT id, code, type FROM t_order
    ORDER BY code
    LIMIT 1000000, 10;
    
    不过,当查询的结果集占表的总行数的很大一部分时,可能就不会走索引了,自动转换为全表扫描。当然了,也可以通过 FORCE INDEX 来强制查询优化器走索引,但这种提升效果一般不明显。
    文章目录
    😊 @ 作者:Lion J
    💖 @ 主页: https://blog.csdn.net/weixin_69252724
    🎉 @ 主题: MySQL__深度分页问题)
    ⏱️ @ 创作时间:2024年04月27日
    ————————————————

在我一次测试中, 100万条数据, 一次偶然的数据展示中, 发现响应数据特别慢, 从前端到后端的一个问题检查上, 最终我是将问题锁定在了一个SQL语句上面. 也就是导致 深度分页问题的罪魁祸首

MySQL 在无法利用索引的情况下跳过1000000条记录后,再获取10条记录

SELECT * FROM t_order ORDER BY id LIMIT 1000000, 10
这块有几种的解决方案:

范围查询
当可以保证 ID 的连续性时,根据 ID 范围进行分页是比较好的解决方案

查询指定 ID 范围的数据

SELECT * FROM t_order WHERE id > 100000 AND id <= 100010 ORDER BY id

也可以通过记录上次查询结果的最后一条记录的ID进行下一页的查询:

SELECT * FROM t_order WHERE id > 100000 LIMIT 10
这种优化方式限制比较大,且一般项目的 ID 也没办法保证完全连续, 并且有可能不是通过ID来查找的

子查询
我们先查询出 limit 第一个参数对应的主键值,再根据这个主键值再去过滤并 limit,这样效率会更快一些。

通过子查询来获取 id 的起始值,把 limit 1000000 的条件转移到子查询

SELECT * FROM t_order WHERE id >= (SELECT id FROM t_order limit 1000000, 1) LIMIT 10;
不过 ,子查询的结果会产生一张新表,会影响性能,应该尽量避免大量使用子查询
并且,这种方法只适用于 ID 是正序的。在复杂分页场景,往往需要通过 过滤条件,筛选到符合条件的 ID,此时的 ID 是离散且不连续的。

延迟关联
延迟关联的优化思路,跟子查询的优化思路其实是一样的: 都是把条件转移到主键索引树,减少回表的次数不同点是,延迟关联使用了 inner join(内连接) 包含子查询。
SELECT t1. FROM t_order t1
INNER JOIN (SELECT id FROM t_order limit 1000000, 10) t2
ON t1.id = t2.id;
还可以使用逗号连接子查询。
SELECT t1.
FROM t_order t1,
(SELECT id FROM t_order limit 1000000, 10) t2
WHERE t1.id = t2.id;
覆盖索引
索引中已经包含了所有需要获取的字段的查询方式称为覆盖索引。

覆盖索引的好处

避免 InnoDB 表进行索引的二次查询,也就是回表操作: InnoDB 是以聚集索引的顺序来存储的,对于 InnoDB 来说,二级索引在叶子节点中所保存的是行的主键信息,如果是用二级索引查询数据的话,在查找到相应的键值后,还要通过主键进行二次查询才能获取我们真实所需要的数据。
而在覆盖索引中,二级索引的键值中可以获取所有的数据,避免了对主键的二次查询(回表),减少了 IO 操作,提升了查询效率。
可以把随机 IO 变成顺序 IO 加快查询效率: 由于覆盖索引是按键值的顺序存储的,对于 IO 密集型的范围查找来说,对比随机从磁盘读取每一行的数据 IO 要少的多,因此利用覆盖索引在访问时也可以把磁盘的随机读取的 IO 转变成索引查找的顺序 IO。

如果只需要查询 id, code, type 这三列,可建立 code 和 type 的覆盖索引

SELECT id, code, type FROM t_order
ORDER BY code
LIMIT 1000000, 10;
不过,当查询的结果集占表的总行数的很大一部分时,可能就不会走索引了,自动转换为全表扫描。当然了,也可以通过 FORCE INDEX 来强制查询优化器走索引,但这种提升效果一般不明6显。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
1月前
|
缓存 监控 Java
从 GC 频繁到毫秒级停顿:JVM 内存调优分代配比、晋升机制与架构策略全拆解
本文深入剖析JDK 17下JVM内存调优核心:从分代回收底层逻辑、年轻代/老年代配比规则,到对象晋升机制与四大坑点;涵盖G1/Parallel收集器调优实践、代码/架构级优化策略,并附生产级参数配置与避坑指南,兼顾深度与落地性。
310 3
|
5月前
|
XML Java 开发者
springboot自动装配的基本原理
Spring Boot自动装配基于“约定大于配置”理念,通过@SpringBootApplication、@EnableAutoConfiguration与spring.factories机制,结合条件注解实现智能Bean加载。它根据依赖自动配置组件,大幅简化开发。其核心是AutoConfigurationImportSelector筛选符合条件的配置类,实现按需装配。开发者可专注业务,享受“开箱即用”的便捷体验。(238字)
|
Kubernetes 物联网 数据中心
大规模 IoT 边缘容器集群管理的几种架构 -2-HashiCorp 解决方案 Nomad
大规模 IoT 边缘容器集群管理的几种架构 -2-HashiCorp 解决方案 Nomad
|
11月前
|
存储 SQL 关系型数据库
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
|
7月前
|
XML Java 数据格式
Bean的生命周期:从Spring的子宫到坟墓
Spring 管理 Bean 的生命周期,从对象注册、实例化、属性注入、初始化、使用到销毁,全程可控。Bean 的创建基于配置或注解,Spring 在容器启动时扫描并生成 BeanDefinition,按需实例化并填充依赖。通过 Aware 回调、初始化方法、AOP 代理等机制,实现灵活扩展。了解 Bean 生命周期有助于更好地掌握 Spring 框架运行机制,提升开发效率与系统可维护性。
|
SQL 存储 关系型数据库
京东面试:分库分表后,如何深度翻页?
在40岁老架构师尼恩的读者交流群中,有小伙伴在京东面试时遇到了MySQL分库分表后深度分页太慢的问题。本文详细分析了单表和分表场景下的性能问题及优化方法,包括索引覆盖、子查询分页、Join分页、禁止跳页查询、二次查询法等。此外,还介绍了使用ES+HBase的海量NOSQL架构方案。通过这些方法,可以显著提升分页查询的性能,帮助面试者在技术面试中脱颖而出。
京东面试:分库分表后,如何深度翻页?
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
763 3
|
人工智能 Linux iOS开发
操作系统的演变:从批处理系统到现代操作系统
【10月更文挑战第27天】 本文回顾了操作系统的历史,从最早的批处理系统到现代的多任务、多用户操作系统。我们将探讨操作系统的核心概念,包括进程管理、内存管理、文件系统和设备驱动等。我们还将介绍一些著名的操作系统,如Windows、Linux和macOS,并讨论它们的特点和优势。最后,我们将展望操作系统的未来发展趋势。
478 0
|
缓存 关系型数据库 MySQL
一文彻底弄懂MySQL优化之深度分页
【10月更文挑战第24天】本文深入探讨了 MySQL 深度分页的原理、常见问题及优化策略。首先解释了深度分页的概念及其带来的性能和资源问题。接着介绍了基于偏移量(OFFSET)和限制(LIMIT)以及基于游标的分页方法,并分析了它们的优缺点。最后,提出了多种优化策略,包括合理创建索引、优化查询语句和使用数据缓存,帮助提升分页查询的性能和系统稳定性。
1939 1
|
网络协议 安全 Windows
【bat】批处理脚本大全
【bat】批处理脚本大全
1022 2
下一篇
开通oss服务