Mysql--实战篇--大数据量表的分页优化(自增长主键,子查询主键主查询全部,查询条件加索引,覆盖索引等)

server/2025/1/18 1:45:59/

当Mysql数据表存储大量数据时(百万级别数据),分页查询的性能问题是一个常见的挑战。特别是当使用LIMIT和OFFSET时,随着OFFSET的增加,查询性能会显著下降。原因在于MySQL需要扫描并跳过前面的行,这会导致I/O操作和CPU使用率增加。
OFFSET是导致分页查询变慢的主要原因之一。随着OFFSET的增大,MySQL需要扫描并跳过越来越多的行,这会导致查询时间线性增长。因此,应该尽量避免使用OFFSET。

1、索引优化

对于大数据量的分页查询,建议使用表的主键(如id)或唯一列来进行分页。通过这种方式,MySQL可以直接从指定的记录开始读取,而不需要扫描和跳过前面的行。
这就要求主键列或者唯一的列不为空,且是连续的整数最合适。

示例:
假设我们有一个orders表,包含大量订单数据。我们希望每次返回10条记录,并且从上次查询的结果之后继续获取下一页的数据。
sql示例:

-- 第一次查询(获取第 1-10 条记录)
SELECT order_id, order_date, amount 
FROM orders 
WHERE user_id = 123 
ORDER BY order_id 
LIMIT 10;-- 下一页查询(从上次查询的最大order_id开始)
SELECT order_id, order_date, amount 
FROM orders 
WHERE user_id = 123 
AND order_id > 1000  -- 假设上一页的最大order_id是1000
ORDER BY order_id 
LIMIT 10;

优点:

  • 高效:MySQL可以直接从指定的order_id开始读取,而不需要扫描和跳过前面的行。
  • 可扩展:即使数据量非常大,查询性能也不会随着页码的增加而显著下降。

注意事项:

  • 确保order_id列上有索引,以便查询能够快速定位到指定的记录。
  • 如果order_id不是唯一的,或者有重复值,可以考虑使用复合条件(如order_id和created_at)来确保唯一性。

2、覆盖索引

覆盖索引是指索引中包含了查询所需的所有列,这样查询可以直接从索引中获取数据,而不需要访问表的数据页。对于分页查询,覆盖索引可以显著减少I/O操作,提升查询性能。

示例:
假设我们经常对orders表进行分页查询,并且每次都查询order_id、order_date和amount列。我们可以在这些列上创建一个组合索引。
sql示例:

CREATE INDEX idx_order_id_date_amount ON orders (order_id, order_date, amount);

优点:

  • 减少I/O操作:查询可以直接从索引中获取所有需要的数据,而不需要访问表的数据页。
  • 提高查询速度:覆盖索引可以显著加快分页查询的速度,尤其是在数据量较大的情况下。

3、延迟关联(Deferred Join)

对于多表联合查询,先查询主键集合,再根据主键查询完整数据。

sql示例:

第一步:
select id from articles order by id limit 100000, 10;
第二步:
select * from articles where id in (主键集合);

优点:
减少数据扫描量,适用于多表复杂查询。仅查询id不会回表查询,性能相对很快。

缺点:
需要多次查询。

4、伪分页

当翻页至极深处时,可以限制查询范围,提示用户返回首页或前几页。

sql示例:

select * from articles order by id limit 1000;

优点:
用户体验较好,避免性能瓶颈。

缺点:
牺牲极深分页的需求。

5、最终优化方案

(1)、自增长主键

mysql推荐使用自增id作为数据表的主键,不要使用uuid作为数据表的主键。使用uuid作为主键不仅会带来性能上的问题,在查询时也会遇到问题。因为在使用select id from table limit 10000,10 查询id数据时,默认是对id进行排序,返回的是排序后的id结果,如果我们想按插入顺序查询结果,这样查询出来的结果就与我们的需求不相符。
Mysql表的数据行是按照聚簇索引(通常是主键)的顺序存储。uuid则是无序的会增加查询和插入数据的消耗。

(2)、覆盖索引

仅返回查询必要的字段,如果字段少的话,可以创建组合索引实现覆盖索引的效果,避免回表查询。

(3)、子查询

使用子查询仅查询需要的主键id,在对目标id进行查询必要的字段。

select id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10;
(4)、包含方法的优化

对于查询中包含统计函数的方法,性能上从高到低count()≈count(1)>count(id)>count(field),因为mysql()做过优化,会自动选择成本最小的方式查询,前提是只有在Mysql5.6之后的版本才有优化。

综上所述,在查询条件的列上添加索引,自增长主键和子查询的方式是优化大数量表分页查询慢问题的必选方案。如果返回的数量列较少,可以考虑使用覆盖索引进行优化。如果查询包含方法,可以考虑多个方法之间性能的问题作出最优的选择。

乘风破浪会有时,直挂云帆济沧海!!!


http://www.ppmy.cn/server/159224.html

相关文章

.NET 9.0 的 Blazor Web App 项目中 Hash 变换(MD5、Pbkdf2) 使用备忘

一、生成 string 对应的 MD5 码 /// <summary>/// 生成 string 对应的 MD5 码/// </summary>/// <param name"s">需要转换的字符串 string<br/>/// 如果用于远程第三方认证&#xff0c;s username DateTime.Now.Ticks.ToString() 线下传递…

Flink开发中的优化方案

前言 在大数据处理领域&#xff0c;Apache Flink以其高吞吐量、低延迟和强大的状态管理能力&#xff0c;成为了实时流处理的首选框架。然而&#xff0c;随着数据量的不断增长和业务复杂性的提高&#xff0c;如何在Flink开发中实施有效的优化方案&#xff0c;成为了一个亟待解决…

【Leetcode 每日一题 - 扩展】3171. 找到按位或最接近 K 的子数组

问题背景 给你一个数组 n u m s nums nums 和一个整数 k k k。你需要找到 n u m s nums nums 的一个 子数组 &#xff0c;满足子数组中所有元素按位或运算 O R OR OR 的值与 k k k 的 绝对差 尽可能 小 。换言之&#xff0c;你需要选择一个子数组 n u m s [ l . . r ] n…

接口自动化入门 : Http的请求头,请求体,响应码解忻!

在进行接口自动化测试时&#xff0c;你需要了解Http的请求头、请求体和响应码的解析。 本文从3个方面介绍这篇文章 一、Http的请求头 二、请求体 三、响应码解忻 一、Http的请求头 HTTP 请求头是 HTTP 请求中的一部分&#xff0c;用于向服务器传递附加的信息。它包含在 HTTP …

2025 年将是统一网络安全的一年

到 2025 年&#xff0c;网络安全将不再只是 IT 团队专属的技术主题&#xff0c;而是将日益成为董事会层面的优先事项。随着网络攻击的频率和严重性不断增加&#xff0c;董事会将需要能够让他们了解组织安全状况的平台。 Armis 首席执行官 Yevgeny Dibrov 认为&#xff0c;统一网…

C# OpenCV机器视觉:极大值抑制

在一个阳光有些慵懒的午后&#xff0c;阿强像往常一样窝在他那被各种电子元件和线路堆满的实验室里&#xff0c;周围的电脑屏幕闪烁着神秘的代码和复杂的图像&#xff0c;仿佛在诉说着一个个未被解开的科技谜题。阿强最近痴迷于机器视觉领域&#xff0c;而今天&#xff0c;他将…

自动化办公|xlwings简介

xlwings 是一个开源的 Python 库&#xff0c;旨在实现 Python 与 Microsoft Excel 的无缝集成。它允许用户使用 Python 脚本自动化 Excel 操作&#xff0c;读取和写入数据&#xff0c;执行宏&#xff0c;甚至调用 VBA 脚本。这使得数据分析、报告生成和其他与 Excel 相关的任务…

大模型-第三章Prompt工程

快速上手大模型 from zhipuai import ZhipuAI client ZhipuAI(api_key"") # 填写您自己的APIKey response client.chat.completions.create(model"glm-4-plus", # 填写需要调用的模型编码messages[{"role": "system", "conte…