前言

后端开发中为了防止一次性加载太多数据导致内存、磁盘IO都开销过大,经常需要分页展示,这个时候就需要用到MySQL的LIMIT关键字。但你以为LIMIT分页就万事大吉了么,Too young,too simple啊,LIMIT在数据量大的时候极可能造成的一个问题就是深度分页。

案例

这里我以显示电商订单详情为背景举个例子,新建表如下:

CREATE TABLE `cps_user_order_detail` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',`user_id` varchar(32) NOT NULL DEFAULT '' COMMENT '用户ID',`order_id` bigint(20) DEFAULT NULL COMMENT '订单id',`sku_id` bigint(20) unsigned NOT NULL COMMENT '商品ID',`order_time` datetime DEFAULT NULL COMMENT '下单时间,格式yyyy-MM-dd HH:mm:ss',PRIMARY KEY (`id`),KEY `idx_time_user` (`order_time`,`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='用户订单详情';

然后手动向表里插入120W条数据。
现在有个需求:分页展示用户的订单详情,按照下单时间倒序。
表结构精简了,需求也简单。于是哗哗哗的写完代码,提测上线了。早期运行一切正常,可随着订单量的不断增大,发现系统越发的缓慢,还时不时报出几个慢查询
这个时候你就该想到是LIMIT偏移的问题了,没错,不是你的SQL不够优美,就是MySQL自身的机制。
这里我就简单以两条SQL为例,如下图,分别是从100和100W的位置偏移分页,可以看到时间相差很大。这还不算其它数据运算和处理的时间,单一条SQL的查询就耗时一秒以上,在对用户提供的功能里这是不能容忍的(电商里经常要求一个接口的RT不超过200ms)。

这里我们再看下执行计划,如下图所示:

在此先介绍一下执行计划Extra列可能出现的值及含义:

  1. Using where:表示优化器需要通过索引回表查询数据。
  2. Using index:即覆盖索引,表示直接访问索引就足够获取到所需要的数据,不需要通过索引回表,通常是通过将待查询字段建立联合索引实现。
  3. Using index condition:在5.6版本后加入的新特性,即大名鼎鼎的索引下推,是MySQL关于减少回表次数的重大优化。
  4. Using filesort:文件排序,这个一般在ORDER BY时候,数据量过大,MySQL会将所有数据召回内存中排序,比较消耗资源。

再看看上图,同样的语句,只因为偏移量不同,就造成了执行计划的千差万别(且容我小小的夸张一下)。第一条语句LIMIT 100,6type列的值是range,表示范围扫描,性能比ref差一个级别,但是也算走了索引,并且还应用了索引下推:就是说在WHERE之后的下单时间删选走了索引,并且之后的ORDER BY也是根据索引下推优化,在执行WHERE条件筛选时同步进行的(没有回表)。
而第二条语句LIMIT 1000000,6压根就没走索引,type列的值是ALL,显然是全表扫描。并且Extra列字段里的Using where表示发生了回表,Using filesort表示ORDER BY时发生了文件排序。所以这里慢在了两点:一是文件排序耗时过大,二是根据条件筛选了相关的数据之后,需要根据偏移量回表获取全部值。无论是上面的哪一点,都是LIMIT偏移量过大导致的,所以实际开发环境经常遇到非统计表量级不得超过一百万的要求。

优化

原因分析完了,那么LIMIT深度分页在实际开发中怎么优化呢?这里少侠给两点方案。
一是通过主键索引优化。什么意思呢?就是把上面的语句修改成:

SELECT * FROM cps_user_order_detail d WHERE d.id > #{maxId} AND d.order_time>'2020-8-5 00:00:00' ORDER BY d.order_time LIMIT 6;

如上代码所示,同样也是分页,但是有个maxId的限制条件,这个是什么意思呢,maxId就是上一页中的最大主键Id。所以采用此方式的前提:1)主键必须自增不能是UUID并且前端除了传基本分页参数pageNo,pageSize外,还必须把每次上一页的最大Id带过来,2)该方式不支持随机跳页,也就是说只能上下翻页。如下图所示是某知名电商中的实际页面。

二是通过Elastic Search搜索引擎优化(基于倒排索引),实际上类似于淘宝这样的电商基本上都是把所有商品放进ES搜索引擎里的(那么海量的数据,放进MySQL是不可能的,放进Redis也不现实)。但即使用了ES搜索引擎,也还是有可能发生深度分页的问题的,这时怎么办呢?答案是通过游标scroll。关于此点这里不做深入,感兴趣的可以做研究。

小结

写这篇博客是因为前段时间在开发中真实经历到了,并且之前在字节面试中确实也和面试官探讨了一番。知道LIMIT的限制以及优化,在面试中能提到是加分项,不能说到MySQL优化就是建索引,调整SQL(实际上在真实开发中这两种优化方案的成效微乎其微)。毕竟MySQL优化那么牛X的话,就不会有那么多中间件产生了。
我是少侠露飞,爱技术,爱分享。

MySQL深度分页的问题及优化方案:千万级数据量如何快速分页相关推荐

  1. mysql 1千万 like优化_MYSQL千万级数据量的优化方法积累

    1.分库分表 很明显,一个主表(也就是很重要的表,例如用户表)无限制的增长势必严重影响性能,分库与分表是一个很不错的解决途径,也就是性能优化途径,现在的案例是我们有一个1000多万条记录的用户表mem ...

  2. 百万级数据量,千万级数据量是多少,海量数据的优化方案

    百万级数据量,千万级数据量是多少? 这里的百万级,千万级,针对数据库,指的是表的数据条数.有时也指并发事务量. 海量数据的优化方案 Note:    具体优化要结合自身的业务特性 百万级: 这个数据量 ...

  3. MySQL千万级数据量优化方案

    前言 千万级大表如何优化,这是一个很有技术含量的问题,通常我们的直觉思维都会跳转到拆分或者数据分区.除此之外,还有其他的思路和解决方案.根据本人多年的工作经验,做了如下总结. 方案 "千万级 ...

  4. MySQL索引(二)索引优化方案有哪些

    在上一篇文章中,我们介绍了MySQL中常见的索引类型以及每种索引的各自特点,那么这篇文章带你来与我一起看一下聚集索引与二级索引的关系,最后在附上常见的索引优化方案.首先我们还是看一下聚集索引和二级索引 ...

  5. MySQL超过800G的大表优化方案

    当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑.部署.运维的各种复杂度,一般以整型 ...

  6. 倒序查询_mysql大表分页查询翻页优化方案

    mysql分页查询是先查询出来所有数据,然后跳过offset,取limit条记录,造成了越往后的页数,查询时间越长 一般优化思路是转换offset,让offset尽可能的小,最好能每次查询都是第一页, ...

  7. oracle千万级分页优化,oracle千万级数据分页存储过程优化

    随着数据量的增加,Oracle数据库分页存储过程(使用rownum分页)查询性能越来越差,查询时间也越来越长,于是优化势在必行,结合用户一般使用特点(一般看前几页的较多),于是以此为切入点优化原先的存 ...

  8. mysql千万级数据索引查询_mysql千万级数据量根据索引优化查询速度

    (一)索引的作用 索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询sql执行往往需要几十秒甚至更多,5秒以上就已经 ...

  9. mysql数值比中文检索快_MySQL 千万 级数据量根据(索引)优化 查询 速度

    一.索引的作用 索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询sql执行往往需要几十秒甚至更多,5秒以上就已经让 ...

最新文章

  1. arch linux 下 安装搭建python机器学习环境
  2. send和WSASend区别
  3. 系统调用的实现(与errno的设置)
  4. 10 QM配置-检验计划配置-维护检验批来源并分配检验类型
  5. 百度UEditor控件中的map组件不支持https使用的问题解决
  6. 团建之后,我想离职了
  7. Python升级后pip命令失效解决方法
  8. mysql封装增删改查_jdbc封装一行代码实现增删改查
  9. Hive数据导出入门
  10. NOIP经典基础模板总结
  11. 为什么读大学时做学术比搞项目重要?
  12. 开源爬虫框架各有什么优缺点?
  13. 第一次作业+105032014140
  14. 中卫市地图arcgis数据shp道路地名县区边界水系2021年(下载说明)
  15. 计算机太极之光,3000多名研究生赛太极,五大太极拳流派名家展风采
  16. 2021牛客暑假多校第二场 K题—Stack (链表)
  17. 计算机网络维护日记,计算机网络维护实习日记.doc
  18. System.Security.SecurityException: 未找到源,但未能搜索某些或全部事件日志。不可 访问的日志: Security
  19. Java基础之map总结
  20. 计算机复试问题总结(一)

热门文章

  1. 【机器学习快讯】20150128机器学习快讯
  2. 逃脱只会部署集群系列 —— Kubeadm部署v1.18.0与ETCD操作
  3. HTMLCSS笔记 [全文字数4w]
  4. 【狂神说Java】Docker最新超详细版教程通俗易懂
  5. C++实现double factorial双阶乘的算法(附完整源码)
  6. 英语练习90 What's your type
  7. 機器學習基石 机器学习基石 (Machine Learining Foundations) 作业2 Q16-18 C++实现
  8. 成都七中2021级高考成绩查询,2021年成都各高中高考成绩排名及放榜最新消息
  9. Qt ASSERT:QMetaObjectPrivate::get(smeta)-revision= 7in file kernel\qobject.cpp,line 2646
  10. 计算机存储程序错误检验,内存错误怎么办?内存错误的修复与检测方法介绍