当前位置: 首页 > article >正文

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

当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.kler.cn/a/507048.html

相关文章:

  • 虚拟拨号技术(GOIP|VOIP)【基于IP的语音传输转换给不法分子的境外来电披上一层外衣】: Voice over Internet Protocol
  • ubuntu20.04安装MySQL5.7
  • 深入云电脑PC Farm技术探讨,以阿里云、华为云、ToDesk为例
  • 【Linux】Mysql部署步骤
  • C++算法第十六天
  • 【GIS操作】使用ArcGIS Pro进行海图的地理配准(附:墨卡托投影对比解析)
  • 如何使用wireshark 解密TLS-SSL报文
  • 深度学习-84-RAG技术之Facebook AI Similarity Search工具Faiss基础应用示例
  • 【单片机开发 - STM32(H7)】启动流程、方式、烧录方式详解
  • JS Clipboard API
  • 本地部署Web-Check网站检测与分析利器并实现远程访问实时监测
  • python爬虫笔记
  • 当PHP遇上区块链:一场奇妙的技术之旅
  • 【Python】使用python 对excel文件进行加密
  • 基于SpringCloud的广告系统设计与实现(一)
  • vscode 切换文件时,修改内容时很卡,怎么解决?
  • No.33 笔记 | Docker入门:基础概念与实用指南
  • wordpress的火车头商品发布接口
  • iOS面试模版
  • 赤店商城系统点餐小程序多门店分销APP共享股东h5源码saas账号独立版全插件全开源
  • 学习threejs,使用OrbitControls相机控制器
  • STM32的集成开发环境STM32CubeIDE安装
  • spark,读取和写入同一张表问题
  • 掌握 TypeScript 的 `Omit` 工具类型:灵活操作对象属性的艺术
  • [Qt]常用控件介绍-布局管理器-QVBoxLayout、QHBoxLayout、QGridLayout、QFormLayout、QSpace控件
  • AI实验室copilot自动化科研,AMD联手约翰霍普金斯大学:成本节约84%!