mysql千万级分页查询SQL优化

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: mysql千万级分页查询SQL优化

场景

某后台的功能列表,页面底部为通用分页:

总条数: 16209321 页码:1 2 3 4 5 .... 9819

页面默认展示 10 条数据,默认展示条数可选。

页面上部分搜索区域部分有多达 20-30 的筛选条件,筛选条件分别来自于不下 10 张数据表。 拿订单列表查询举例,可以使用用户表里的某个特殊字段进行筛选,如性别等,这些字段肯定不会在订单表存储,所以必然会进行联表。

使用者常常有疑问: 为何页面只有 10 条数据,查询却如此之慢?

老板会质疑你,做的是什么玩意?查询 10 条数据都要 1 分钟以上的时间?(优化前页面需要转 1 分钟才可显示出数据,页面转圈圈~)

这个功能对应的是后台的一个千万级别的大表,未分库分表,目前的数据量为13755695,分页查询使用到了limit,优化之前的查询耗时30 s,按照下文的方式调整SQL后,耗时800 ms; 

关于分页的优化

使用limit分页时的MySQL并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。【阿里巴巴JAVA开发手册】

select * from big_table where data_type in (1,2) limit 1000000,10; ## 耗时:39.23s

分页查询优化方式

1.基于主键ID实现查询优化分页查询优化

select * from big_table where id > (select id from big_table where data_type in (1,2) limit 1000000,1) limit 10; ## 耗时:0.716s

优化缺陷:如果主键不是自增长的(如uuid方式),则此方法失效;如果查询要求中需要针对一些字段进行过滤查询,如big_table中有一个data_type的字段,取值范围1,2,3。现在在查询中我们固定使用1,2进行查询,那么此方法也会失效,因为你根据条件筛选出最大的id后,后面10个数据,不一定都是你想要的,可能包含data_type=3的数据。

2.基于主键ID实现查询优化分页查询优化

select * from big_table a inner join (select id from big_table where data_type in (1,2) limit 1000000,10) b on a.id = b.id; ##耗时:0.69s

先快速定位需要获取的id段,然后再关联;

关于count的优化

在第一次优化后艰难使用一段时间后,依然遭到投诉,想了想,遭到投诉也是必然的,50 秒开一个页面。决定再次优化,本次的考虑点如下:

1、 由于时间慢是因为 count 语句造成,count 语句大约需要 40 多秒的时间,实际数据查询经过了第一次优化只需要不到十秒。而 count 函数又是必不可少的,因为需要查询总数,以供分页显示总条数及最后一页,所以必须从 count 优化入手

2、 如果技术上优化遇到了瓶颈,或者说 mysql 已经优化到极致,那么能否从业务上解决?

优化分析主要从两个角度进行。

1、 从技术角度来看,查询必有筛选条件,由于几十个筛选条件的取值不确定性,通过缓存 count 的总条数是无法满足的。继续观察 mysql 索引情况,由于现有索引的 key_len 过大,可以通过建立较小的索引 (使用小字段) 来为排序使用,由于我们的业务查询必有时间段条件,固为时间段字段单独建立索引,由此带来了几秒的性能提升 (并不明显)。

2、 从业务角度看,我们观察了百度、google、微博等网站,分页都不会显示结果集的总条数以及也不会有最后一页的链接,都是通过点击下一页的方式不断检索后面的数据,也就没有使用 count 函数的必要了,经过与需求方沟通,发现我们的想法并不复合需求,由于是后台管理系统,是需要通过筛选条件实时查询总条数,固此优化想法 pass。

3、 通过沟通,得到另一个优化方向,可以将前端分页组件异步加载。首先将数据列表展示出来,方便其它操作。前端调整逻辑,分别调用 2 次接口,获取数据接口、获取分页结果接口。分页结果接口返回数据前,分页组件显示 “正在努力加载…” 字样。

此种优化最终实现:列表数据加载 <5 秒,分页组件加载 >40 秒

其他优化思路

通过学习研究发现,mysql innodb 引擎在有索引、有 where 条件的情况下,count 速度并不慢,所以问题一样还出在 sql 上。

1, 通过分析 sql 发现,由于查询条件众多,只是对 where 语句后面的 sql 进行了动态 sql 处理,而 left join 语句没有进行动态 sql 处理,导致不管有几个查询条件,都需要链接 10 张左右其它数据表。是链接查询限制了 sql 的性能!而不是 count 限制的 sql 的性能! 固做以下优化,将 left join 一并使用动态 sql 链接:

2.与需求方沟通后,查询列表可去掉排序规则,使用默认排序即可。此点优化也十分重要,order by 会导致 file sort,而极大的影响查询性能,所以我们去掉了 order by 语句,而使用默认的 id 排序。

3.最终优化: 列表数据查询 130ms,分页插件查询 (count 查询)150ms,目前数据单表数据量级在 2000 万左右,以次时间效率推断,多查询条件的复杂分页查询,可以支持单表几亿没有问题。

 

参考文章

https://zhuanlan.zhihu.com/p/457709985

https://blog.51cto.com/u_7117633/2850318

https://learnku.com/articles/53559

 

本篇文章如有帮助到您,请给「翎野君」点个赞,感谢您的支持。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
177 9
|
13天前
|
SQL 关系型数据库 MySQL
MySQL派生表合并优化的原理和实现
通过本文的详细介绍,希望能帮助您理解和实现MySQL中派生表合并优化,提高数据库查询性能。
51 16
|
27天前
|
SQL 存储 关系型数据库
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
本文详细介绍了MySQL中的SQL语法,包括数据定义(DDL)、数据操作(DML)、数据查询(DQL)和数据控制(DCL)四个主要部分。内容涵盖了创建、修改和删除数据库、表以及表字段的操作,以及通过图形化工具DataGrip进行数据库管理和查询。此外,还讲解了数据的增、删、改、查操作,以及查询语句的条件、聚合函数、分组、排序和分页等知识点。
【MySQL基础篇】全面学习总结SQL语法、DataGrip安装教程
|
14天前
|
SQL 关系型数据库 MySQL
MySQL派生表合并优化的原理和实现
通过本文的详细介绍,希望能帮助您理解和实现MySQL中派生表合并优化,提高数据库查询性能。
33 7
|
1天前
|
缓存 关系型数据库 MySQL
【深入了解MySQL】优化查询性能与数据库设计的深度总结
本文详细介绍了MySQL查询优化和数据库设计技巧,涵盖基础优化、高级技巧及性能监控。
10 0
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
79 18
|
1月前
|
SQL Oracle 数据库
使用访问指导(SQL Access Advisor)优化数据库业务负载
本文介绍了Oracle的SQL访问指导(SQL Access Advisor)的应用场景及其使用方法。访问指导通过分析给定的工作负载,提供索引、物化视图和分区等方面的优化建议,帮助DBA提升数据库性能。具体步骤包括创建访问指导任务、创建工作负载、连接工作负载至访问指导、设置任务参数、运行访问指导、查看和应用优化建议。访问指导不仅针对单条SQL语句,还能综合考虑多条SQL语句的优化效果,为DBA提供全面的决策支持。
70 11
|
4天前
|
SQL 分布式计算 Java
Spark SQL向量化执行引擎框架Gluten-Velox在AArch64使能和优化
本文摘自 Arm China的工程师顾煜祺关于“在 Arm 平台上使用 Native 算子库加速 Spark”的分享,主要内容包括以下四个部分: 1.技术背景 2.算子库构成 3.算子操作优化 4.未来工作
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
75 7
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
102 5