MySQL百万级数据,怎样做分页查询

 更新时间:2023年10月26日 10:58:22   作者:ZNineSun  
这篇文章主要介绍了MySQL百万级数据,怎样做分页查询?今天咱们就来聊聊这个话题,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

MySQL百万级数据,如何做分页查询

随着业务的增长,数据库的数据也呈指数级增长,拿订单表为例,之前的订单表每天只有几千个,一个月下来不超过十万。

而现在每天的订单大概就是2w+,目前订单表的数据已经达到了700w。

这带来了各种各样的问题,今天我先从一个小问题开始。

之前所写的代码mysql的分页都是采用的limit方式进行,这种方式固然代码比较简单,但数据量大了之后真的是查的慢。

所以此处涉及到mysql大数据量后的分页查询方法及其优化技巧

方法1:直接使用数据库提供的SQL语句

语句样式: MySQL中,可用如下方法:

SELECT * FROM 表名称 LIMIT M,N

适应场景:适用于数据量较少的情况(元组百/千级)

原因/缺点:全表扫描,速度会很慢 且有的数据库结果集返回不稳定(如某次返回1,2,3,另外的一次返回2,1,3)。

Limit限制的是从结果集的M位置处取出N条输出,其余抛弃。

再具体进行测试之前,我们需要先创建100w条测试数据,推荐使用存储过程进行创建

  • 创建存储过程
DROP PROCEDURE IF EXISTS create_user_tel;
create procedure create_user_tel() 
begin 
    declare id int; 
    set id=1;
    while id <=1000000
      do 
        INSERT INTO `user01` VALUES(id,  'test123', 'm');
        set id=id+1;
    end while;
end;
  • 执行存储过程
call create_user_tel();

下面开始测试这种方法


在这里插入图片描述

可以看到我表里总共80w条数据,我们看看用这种方法来分页查询的耗时

select * from user01 limit 780000, 20;

在这里插入图片描述

像这种分页最大的页码页显然这种时间是无法忍受的,同时大家可以自行测试一下limit 100 20 ,limit 1000 20,limit 10000 20等所耗费的时间,不难发现limit语句的查询时间与起始记录的位置成正比

方法2:建立主键或唯一索引, 利用索引(假设每页10条)

语句样式:MySQL中,可用如下方法:

SELECT id FROM 表名称 WHERE id > (pageNum*10) LIMIT M
  • 适应场景:适用于数据量多的情况(元组数上万)
  • 原因:索引扫描,速度会很快。

我们都知道,利用了索引查询的语句中如果只包含了那个索引列(覆盖索引),那么这种情况会查询很快。

因为利用索引查找有优化算法,且数据就在查询索引上面,不用再去找相关的数据地址了,这样节省了很多时间。另外Mysql中也有相关的索引缓存,在并发高的时候利用缓存就效果更好了。

在我们的例子中,我们知道id字段是主键,自然就包含了默认的主键索引。现在让我们看看利用覆盖索引的查询效果如何。

这次我们之间查询最后一页的数据(利用覆盖索引,只包含id列),如下:

select id from user01 limit 780000, 20;

上面这个语句只能查询id,如果我们也要查询所有列,有两种方法:

  • 一种是id>=的形式
  • 另一种就是利用join
SELECT * FROM user01 
WHERE id > =(
select id from user01 limit 780000, 1) 
limit 20

另一种写法

SELECT * FROM user01 a JOIN 
(select id from user01 limit 780000, 20) b 
ON a.id = b.id

自己可以操作一下就会发现效率会大幅度提升,如果你发现这些语句速度差别不大的话,性能的限制还有可能是你服务器或自己的电脑性能不足导致的

通过主键或者索引的方式去查询可能会出现一个致命的问题就是数据查询出来并不是按照主键或者索引排序的,所以会有漏掉数据的情况

这种情况可以通过方法三来解决

方法3:基于索引再排序

语句样式:MySQL中,可用如下方法:

SELECT * FROM 表名称 
WHERE id_pk > (pageNum*10) 
ORDER BY id_pk ASC LIMIT M
  • 适应场景:适用于数据量多的情况(元组数上万). 最好ORDER BY后的列对象是主键或唯一索引,使得ORDERBY操作能利用索引被消除但结果集是稳定的(稳定的含义,参见方法1)
  • 原因:索引扫描,速度会很快.
SELECT * FROM user01 
WHERE id >= 780000
ORDER BY id ASC LIMIT 20

在这里插入图片描述

这种方式会让我们的查询效率得到更大的提升

方法4:基于索引使用prepare

语句样式:MySQL中,可用如下方法:

PREPARE stmt_name FROM SELECT * FROM 表名称 WHERE id_pk > (?* ?) ORDER BY id_pk ASC LIMIT M

第一个问号表示pageNum,第二个问号表示每页元组数。

  • 适应场景:大数据量
  • 原因:索引扫描,速度会很快。

prepare语句又比一般的查询语句快一点。

方法5:利用MySQL支持ORDER操作可以利用索引快速定位部分元组,避免全表扫描。

比如:读第1000到1019行数据

SELECT * FROM your_table 
WHERE id>=780000 
ORDER BY id ASC 
LIMIT 0,20

在这里插入图片描述

可以发现这种效率和上面方法的效率差不多,因为效率的提升的原因都是走id主键索引

方法6:利用"子查询/连接+索引"快速定位元组的位置,然后再读取元组

SELECT * FROM your_table 
WHERE id <= 
(SELECT id FROM your_table 
ORDER BY id desc 
LIMIT ($page-1)*$pagesize 
ORDER BY id desc 
LIMIT $pagesize

利用连接示例:

SELECT * FROM your_table AS t1 
JOIN (
SELECT id FROM your_table 
ORDER BY id desc LIMIT ($page-1)*$pagesize 
) AS t2 
WHERE t1.id <= t2.id 
ORDER BY t1.id desc LIMIT $pagesize;

我个人实验之后发现效率极其低下

综上:

如果对于有where 条件,又想走索引用limit的,必须设计一个索引,将where 放第一位,limit用到的主键放第2位,而且只能select 主键!

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解决MySQL客户端输出窗口显示中文乱码问题的办法

    解决MySQL客户端输出窗口显示中文乱码问题的办法

    这篇文章主要介绍了解决MySQL客户端输出窗口显示中文乱码问题的办法,需要的朋友可以参考下
    2015-12-12
  • MySQL的主键命名策略相关

    MySQL的主键命名策略相关

    这篇文章主要介绍了MySQL的主键命名策略的的相关资料,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2021-01-01
  • mysql优化连接数防止访问量过高的方法

    mysql优化连接数防止访问量过高的方法

    这篇文章主要介绍了mysql优化连接数防止访问量过高的方法,需要的朋友可以参考下
    2014-06-06
  • sql跨表查询的三种方案总结

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

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

    解读SQL语句中要不要加单引号的问题

    这篇文章主要介绍了关于SQL语句中要不要加单引号的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • RPM方式安装MySQL5.6源码

    RPM方式安装MySQL5.6源码

    这篇文章主要为大家分享了RPM方式安装MySQL5.6源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • MySQL对小数进行四舍五入的操作实现

    MySQL对小数进行四舍五入的操作实现

    数学函数是MySQL中常用的一类函数,其主要用于处理数字,包括整型和浮点数等等,本文主要介绍了MySQL对小数进行四舍五入的操作实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • MySQL优化insert性能的方法示例

    MySQL优化insert性能的方法示例

    对于一些数据量较大的系统,数据库面临的问题除了查询效率低下,还有就是数据入库时间长。下面这篇文章主要给大家介绍了关于MySQL优化insert性能的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-06-06
  • MySql数据库单表查询与多表连接查询效率对比

    MySql数据库单表查询与多表连接查询效率对比

    在遇到数据之间的联系很复杂,建表就很纠结,到底该怎么去处理这些复杂的数据呢,是单表查询,然后在业务层去处理数据间的关系,还是直接通过多表连接查询来处理数据关系呢
    2021-09-09
  • MySQL嵌套查询实例详解

    MySQL嵌套查询实例详解

    这篇文章主要介绍了MySQL嵌套查询的使用技巧,结合实例形式较为详细的分析了MySQL嵌套查询参数设置、使用方法与注意事项,需要的朋友可以参考下
    2015-12-12

最新评论