Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >百万数据分页查询优化方案

百万数据分页查询优化方案

作者头像
关忆北.
发布于 2023-10-11 01:41:13
发布于 2023-10-11 01:41:13
38800
代码可运行
举报
文章被收录于专栏:关忆北.关忆北.
运行总次数:0
代码可运行
分页问题

分页列表查询是项目中的热点需求,这种需求的特点是:字段多、数据量大、访问频繁、使用率高的特点,这个功能是给用户最直观的展示系统的信息,针对于多、大、频、热这几个特点,会引申出一个问题:列表展示的数据可能是来自于不同的数据维度、需要关联N张表查询得到,那么,如何让用户更快、更准的获取到需要的数据,便成了程序员在编码时需要考虑到并且需要解决的问题,因为随时间推移,线上系统不乏几百万数据的表。

准备
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE `test_temp` (
  `test_id` int NOT NULL AUTO_INCREMENT,
  `field_1` varchar(20) DEFAULT NULL,
  `field_2` varchar(20) DEFAULT NULL,
  `field_3` bigint DEFAULT NULL,
  `create_date` date DEFAULT NULL,
  PRIMARY KEY (`test_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

写一个存储过程生成200万测试数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
drop procedure if exists test_insert;
create procedure test_insert(n int)
begin
    declare v int default 0;
    SET AUTOCOMMIT = 0;
    while v < n
        do
            insert into test_temp(field_1, field_2, field_3, create_date)
            values (concat('testing',v),
                    substring(md5(rand()), 1, 10),
                    floor(rand() * 1000000),
                    adddate('1970-01-01', rand(v) * 10000));
            set v = v + 1;
        end while;
    SET AUTOCOMMIT = 1;
end;

插入数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
call test_insert(2000000);

测试数据方案来自于:

https://blog.csdn.net/weixin_38924697/article/details/119978916

现象

带分页的语句,我们一般使用Limit实现,那么基于以上数据我们写一个SQL:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * from test_temp LIMIT 1,10

执行时间:0.004秒

此时,我们模拟分页数据特别往后的情况,分页数据越往后越慢。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT SQL_NO_CACHE * from test_temp LIMIT 19999900,10

执行时间:1.348秒,速度慢了二十余倍。

实际的业务场景下,可能会关联N张表,而且线上服务器的压力会比单机开发环境更重,因此实际接口响应时间会更长。

问题原因
  1. 回表:查询频率高的字段会建立索引,但是并不是所有的查询字段都会在索引上,无法命中索引的字段则需要回表,回表是IO操作,因为需要根据索引查找到数据行后,再根据数据行的主键或唯一索引去聚簇索引中查找具体的数据行。因此在执行回表操作时需要从磁盘读取数据,而磁盘IO是相对较慢的操作。
  2. 查询规则:limit 19999900,10并不是从第19999900行开始扫描,使用explain查看执行计划:
解决方案

当查询的字段都被索引覆盖时,可无需回表,那么我们可以先查询出主键id,再根据主键id拼接id条件或者作为临时表JOIN原表就可以了。因为主键id是最快的索引:聚簇索引,通过id就能快速找到指定行。

查询方案一:

先查询出id,再根据id直接查询数据。

查询出id
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT test_id from test_temp LIMIT 1999995,5

执行计划:

再根据这些id为条件查询数据
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * from test_temp WHERE test_id in (2952993,2952995,2952996,2952997)

优化后的查询时间为:0.002秒。

执行计划

查询方案二:

使用子查询作为临时表Inner join主表查询:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * from (SELECT test_id from test_temp LIMIT 1999995,5) as temp INNER JOIN test_temp tt on tt.test_id = temp.test_id

整体查询时间:0.245秒

执行计划:

性能对比

在不考虑MySQL执行时校验权限、建立连接的情况下,两种方案整体查询时间在0.25秒左右,相比于整体查询的1.34秒具有较大优势。方案一相较于方案二的SQL语句更加简洁易懂,而方案二只需与MySL建立一次查询即可。

其他优化项

请参考:

百万查询注意点

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-07-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL不走索引的情况分析
当数据库查询命中索引时,数据库会首先利用索引列的值定位到对应的数据节点。这个数据节点上记录了对应数据行的行标识符(Row Identifier)。然而,如果查询需要获取该行其他列的数据,就需要进行回表操作。
关忆北.
2023/10/11
3530
MySQL不走索引的情况分析
MySQL实现批量Insert和分页查询
DROP PROCEDURE IF EXISTS test_insert;--如果存在此存储过程则删掉
浩Coding
2019/07/03
4.3K0
MySQL实现批量Insert和分页查询
MySQL-字节千万级数据分页查询优化方案
1、先查询出90万+10条记录的id,回表查询数据,再将90万+10条完整记录发给MySQL以便筛选最后10条; 2、先查询出90万+10条记录的id,筛选出最后10条记录的id再回表查询,最后返回10条完整记录给MySQL。 在回表次数很多(limit决定)的情况下,显然第二种方法是比较快的,但是MySQL默认采用了第一种。
公众号 云舒编程
2024/01/25
3740
MySQL-字节千万级数据分页查询优化方案
MySQL - 分页查询优化的两个案例解析
任何一个系统,分页查询都是必不可少的吧 ,MySQL中的分页查询 就是 limit呗 ,你有没有感觉到 越往后翻页越慢 ,常见的SQL如下
小小工匠
2021/08/17
1.3K0
Mysql索引知识详谈
原文地址:https://www.t-io.org/1159984867644153856
talent-tan
2019/08/10
3210
千万级数据深分页查询SQL性能优化实践
Tech 导读 分页查询在数据库中是一种很常见的应用场景,一般都可以使用limit语句快速实现。但是随着表数据的增长,limit查询性能也会越来越慢。
京东技术
2023/11/13
7260
千万级数据深分页查询SQL性能优化实践
数据库查询优化技术(二):子查询优化
对应的是限制条件(格式类似“field<op>consant”, field表示列对象,op是操作符如"="、">"等)。
sunonzj
2022/06/21
3.4K0
数据库查询优化技术(二):子查询优化
MySQL索引(六)索引优化补充,分页查询、多表查询、统计查询
本文若未特意说明使用的数据表,均为 MySQL索引(四)常见的索引优化手段 中的示例表。
鳄鱼儿
2024/05/21
3770
MySQL索引(六)索引优化补充,分页查询、多表查询、统计查询
Peewee 使用手册
文章目录 Peewee 是什么 如何使用 基本步骤 连接数据库 创建数据表 插入一条数据记录 获取条件过滤后的数据记录 更新数据记录 查询单条数据记录 其他要点 Peewee 是什么 Peewee 即 Python OMR 框架之一。 如何使用 基本步骤 通过 pip3 下载 peewee 新建 models.py 模型文件 在 models.py 中加入以下基础代码 运行 models.py,在 mysql 中生成 new_record 表 连接数据库 from peewee import *
星辉
2021/03/04
1.2K0
MySQL数据库优化方案测试-亿级银行交易数据的查询
点击上方蓝字关注我们吧 作者:逸宸a 链接:https://www.jianshu.com/p/cbdef47fb837 对MySQL的性能和亿级数据的处理方法思考,以及分库分表到底该如何做,在什么场景比较合适? 比如银行交易流水记录的查询 限盐少许,上实际实验过程,以下是在实验的过程中做一些操作,以及踩过的一些坑,我觉得坑对于读者来讲是非常有用的。 首先:建立一个现金流量表,交易历史是各个金融体系下使用率最高,历史存留数据量最大的数据类型。现金流量表的数据搜索,可以根据时间范围,和个人,以及金额进
腾讯云数据库 TencentDB
2019/06/11
9940
MySQL数据库优化方案测试-亿级银行交易数据的查询
分享 | MySQL百万级数据分页查询及优化
方法5: 利用MySQL支持ORDER操作可以利用索引快速定位部分元组,避免全表扫描
用户1516716
2019/05/22
2.3K1
浅谈MySQL分页查询的工作原理
MySQL 的分页查询在我们的开发过程中还是很常见的,比如一些后台管理系统,我们一般会有查询订单列表页、商品列表页等。
政采云前端团队
2023/11/09
2.2K0
浅谈MySQL分页查询的工作原理
MySQL具体解释(19)———-海量数据分页查询优化
查看代码打印1 SELECT * FROM table ORDER BY id LIMIT 1000,10; 以上SQL语句在原理上和在实际操作中是不会存在什么问题,可是当table表的数据量达到几十万以上的时候。上面的语句运行一遍,可能会要运行个十几秒的时间,而且当页数越靠后的话,运行的时间会越长。这个时候我们就须要找到一种更快的查询办法来替代这样的操作了。
全栈程序员站长
2022/01/28
1.2K0
第10章_索引优化与查询优化
🧑个人简介:大家好,我是 shark-Gao,一个想要与大家共同进步的男人😉😉
程序员Leo
2023/08/02
5100
第10章_索引优化与查询优化
Mysql面试题及千万级数据查询优化
今天在说Mysql查询优化之前,我先说一个常见的面试题,并带着问题深入探讨研究。这样会让大家有更深入的理解。
攻城狮的那点事
2019/09/17
1.4K0
Mysql面试题及千万级数据查询优化
重新学习MySQL数据库12:从实践sql语句优化开始
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看
Java技术江湖
2019/12/02
5390
mysql大数据量分页查询优化总结
传统分页查询:SELECT c1,c2,cn… FROM table LIMIT n,m
全栈程序员站长
2022/07/19
1.6K0
MySQL深分页,limit 100000,10 优化
我们日常做分页需求时,一般会用limit实现,但是当偏移量特别大的时候,查询效率就变得低下。本文将分4个方案,讨论如何优化MySQL百万数据的深分页问题.
寻求出路的程序媛
2024/06/05
9160
MySQL深分页,limit 100000,10 优化
MySQL 之 索引原理与慢查询优化
浏览目录 一 索引介绍 二 索引方法 三 索引类型 四 聚合索引和辅助索引  五 测试索引 六 正确使用索引 七 组合索引 八 注意事项 九 查询计划 十 慢日志查询 十一 大数据量分页优化 1. 索引介绍   一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化显然是重中之重。 说起加速查询,就不得不提到索引了。 什么索引:    简单的说,相当于图书的目录,可以帮助用
人生不如戏
2018/04/10
1.3K0
MySQL 之 索引原理与慢查询优化
MySQL索引和查询优化
基数是数据列所包含的不同值的数量,例如,某个数据列包含值 1、3、7、4、7、3,那么它的基数就是 4。
网络技术联盟站
2020/10/09
1.4K0
相关推荐
MySQL不走索引的情况分析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验