MySQL深分页问题解决思路

 更新时间:2022年12月22日 14:33:14   作者:MinggeQingchun  
这篇文章主要介绍了优雅地解决mysql深分页问题,本文将会讨论当mysql表大数据量的情况,如何优化深分页问题,并附上最近的优化慢sql问题的案例伪代码,需要的朋友可以参考下

一、MySQL深分页问题

我们在日常开发中,查询数据量比较大的时候,后端基本都会通过前端,移动端传过来的页码,每页数据行数,通过SQL中的 limit 进行分页,如果查询页数比较小的时候,不会出现太大问题,但是如果查询页码比较大的时候,性能就会出现急剧下降瓶颈

如:

假设有一个千万量级的表,取1到10条数据

select column_name1,column_name2... from table limit 0,10;
select column_name1,column_name2... from table limit 1000,10;

这两条语句查询时间应该在毫秒级完成

select column_name1,column_name2... from table limit 1000000,10;

这条语句执行之间在秒级完成,查询效率低下,还可能导致接口超时

使用select column_name1,column_name2... from table_name表名 limit offset, rows 的情况下直接⽤limit 1000000,10 扫描的是约100万条数据,并且是需要回表100W次,也就是说⼤部分性能都耗在随机访问上,到头来只⽤到10条数据(总共取1000010条数据只留10条记录)

这种查询的慢,其实是因为 limit 后面的偏移量太大导致的

1、limit 语法解读

limit用于数据的分页查询,也会用于数据的截取,limit的用法:

SELECT column_name1,column_name2... FROM table_name表名 LIMIT offset,rows
或
SELECT column_name1,column_name2... FROM table_name表名 LIMIT rows OFFSET offset  

注:

table_name :表名

column_name:字段名

第一种:SELECT * FROM table LIMIT offset, rows # 常用形式

-- 从0开始,截取5条记录,即检索行为1到5
SELECT column_name1,column_name2... FROM table_name表名 limit 0,5
-- 注意: 关键字limit后面的两个参与用逗号分割

第二种:SELECT * FROM table LIMIT rows OFFSET offset

-- 从0开始,截取5条记录,即检索行为1到5
SELECT column_name1,column_name2... FROM table_name表名 limit 5 offset 0
-- 注意: 使用limit和offset两个关键字,并且各带一个参数,中间没有逗号分割

第三种:SELECT * FROM table LIMIT rows

-- 截取记录的前五行数据,可以理解为offset的默认值为0
SELECT column_name1,column_name2... FROM table_name表名 limit 5

2、回表

回表,顾名思义就是回到表中,也就是先通过普通索引扫描出数据所在的行,再通过行主键ID取出索引中未包含的数据。所以回表的产生也是需要一定条件的,如果一次索引查询就能获得所有的select记录就不需要回表,如果select所需获得列中有其他的非索引列,就会发生回表动作。即基于非主键索引的查询需要多扫描一棵索引树

主键索引树的叶子节点直接就是我们要查询的整行数据,而非主键索引的叶子节点是主键的值,查到主键的值以后,还需要再通过主键的值再进行一次查询

回表,简单说就是mysql内部需要经过两次查询

第一次先索引扫描,然后再通过主键去取索引中未能提供的数据

create `table` tb_name(
    `id` int(11) not null auto_increment , 
    `k` int(11) default '0' ,
    `name` varchar(16),
    primary key(id)
    index (k)
)engine=InnoDB;

我们提取id=500这一行的全部数据,这里通过主键id定位到这一行,然后返回数据

select * from T where ID=500;
+-----+---+-------+
| id  | k | name  |
+-----+---+-------+
| 500 | 5 | name5 |
+-----+---+-------+

这里我们先通过普通索引,搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程即为回表

select * from T where k=5;
+-----+---+-------+
| id  | k | name  |
+-----+---+-------+
| 500 | 5 | name5 |
+-----+---+-------+

二、优化方案

(一)模仿百度、谷歌方案(前端业务控制)

类似于分段。我们给每次只能翻100页、超过一百页的需要重新加载后面的100页。这样就解决了每次加载数量数据大 速度慢的问题了

这种方式比较简单粗暴,就是不允许查看这么靠后的数据

(二)索引覆盖 + 子查询

根据主键 id,在上面建了索引,先在索引树中找到开始位置的 id 值,再根据找到的 id 值查询行数据

SELECT 
    id,name,age 
FROM
    t_user user
WHERE
    user.id = (select MIN(id) from t_user where age = #{age})
SELECT 
    id,name,age 
FROM 
    t_user 
WHERE 
    id >= (SELECT id FROM t_user order by id LIMIT 80000,1) 
LIMIT 10

(三)起始位置重定义(记录每次取出的最大id, 然后where id > 最大id)

这种方法适用于:除了主键ID等离散型字段外,也适用连续型字段datetime等

最大id由前端分页 pageNum 和 pageIndex 计算出来

select * from table_name Where id > 最大id limit 10000, 10;

到此这篇关于MySQL深分页问题解决思路的文章就介绍到这了,更多相关MySQL深分页内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL 备份还原数据库批处理

    MySQL 备份还原数据库批处理

    在日常工作中,我们往往需要对MySQL数据库进行备份,有时可以通过拷贝整个文件,有时通过备份整个库还有的时候我们就只需要备份某个表。
    2009-07-07
  • 实现MySQL数据库锁的两种方式

    实现MySQL数据库锁的两种方式

    今天我们就来聊一聊数据库的锁,实现数据库锁的两种方式,一个是实现乐观锁的方式,一个是实现悲观锁的实现方式,文中的代码示例介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • 详解Mysql两表 join 查询方式

    详解Mysql两表 join 查询方式

    这篇文章主要介绍了Mysql两表 join 查询方式,主要包括SQL基本语法格式ji3种join方式,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • MySQL数据库中表的操作详解

    MySQL数据库中表的操作详解

    这篇文章主要为大家详细介绍了MySQL数据库中表常用的一些操作方法,文中的示例代码讲解详细, 对我们学习MySQL有一定帮助,需要的可以参考一下
    2022-08-08
  • Mysql如何查看表及字段信息

    Mysql如何查看表及字段信息

    这篇文章主要介绍了Mysql如何查看表及字段信息,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-01-01
  • MySQL 8.0.18 Hash Join不支持left/right join左右连接问题

    MySQL 8.0.18 Hash Join不支持left/right join左右连接问题

    在MySQL 8.0.18中,增加了Hash Join新功能,它适用于未创建索引的字段,做等值关联查询。这篇文章给大家介绍MySQL 8.0.18 Hash Join不支持left/right join左右连接,感兴趣的朋友一起看看吧
    2019-11-11
  • 从云数据迁移服务看MySQL大表抽取模式的原理解析

    从云数据迁移服务看MySQL大表抽取模式的原理解析

    这篇文章主要介绍了从云数据迁移服务看MySQL大表抽取模式的原理解析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • mysql 8.0.11压缩包版本安装教程

    mysql 8.0.11压缩包版本安装教程

    这篇文章主要为大家详细介绍了mysql 8.0.11压缩包版本安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • MySQL ifnull()函数的具体使用

    MySQL ifnull()函数的具体使用

    本文主要介绍了MySQL ifnull()函数的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • sql跨表查询的三种方案总结

    sql跨表查询的三种方案总结

    这篇文章主要介绍了sql跨表查询的三种方案总结,文章围绕主题展开详细的内容,具有一定的参考价值,需要的小伙伴可以参考一下,希望对你的学习有所帮助
    2022-08-08

最新评论