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

news2024/9/22 13:42:08

随着业务的增长,数据库的数据也呈指数级增长,拿订单表为例,之前的订单表每天只有几千个,一个月下来不超过十万。而现在每天的订单大概就是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 主键!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/196351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

国产ETL工具/ETL 产品 (BeeDI ) 集团财务 双向同步 审核平台

项目需求核心 实时同步、双向同步、部分同步、日志解析同步、断点续传 项目需求概要 35分公司财务数据实时同步汇总中心平台 &#x1f51b; 中心平台财务数据实时同步分发35分公司 项目需求内容 35分公司数据中部分表数据同步到中心库对应表&#xff0c;10张表分公司表年数…

【MyBatis】mybatis缓存机制

1. 缓存基础知识:缓存: cache缓存的作用: 通过减少IO的方式, 来提高程序的执行效率mybatis缓存包括:一级缓存: 讲话查询的数据存储到SqlSession中二级缓存: 将查询的数据存储到SqlSessionFactory中或者集成第三方的缓存: 比如EhCache...mybatis缓存只针对DQL语句, 也就是说缓存…

【1145. 二叉树着色游戏】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 有两位极客玩家参与了一场「二叉树着色」的游戏。游戏中&#xff0c;给出二叉树的根节点 root&#xff0c;树上总共有 n 个节点&#xff0c;且 n 为奇数&#xff0c;其中每个节点上的值从 1 到 n 各不…

WPF使用AvalonEdit实现代码高亮显示、搜索、替换功能

很多工程软件拥有自己定义的脚本语言&#xff0c;作为程序员用惯了具有高亮显示和智能提示功能的编辑器&#xff0c;所以针对特定的脚本自己开发一个编辑器。主要采用WPF、C#语言以及AvalonEdit控件。 文章目录AvlonEdit控件实现自定义高亮显示实现文本搜索实现文本替换自定义搜…

磁疗效果因“病”而异,坚持=胜利!

磁疗在我国具有悠久的历史早在春秋战国时期&#xff0c;就有神医扁鹊运用磁疗治病的记载。 北京军区总医院理疗科主任&#xff0c;中华生物磁学研究会秘书长周万松认为&#xff0c;关于磁场改善血液循环这一点是肯定的&#xff0c;磁场可以扩张血管、加速血流、改善血液循环。但…

【H5游戏】-整一个简单的解压小游戏【抽纸巾】

专栏简介 &#x1f492;个人主页 &#x1f4f0;专栏目录 点击上方查看更多内容 &#x1f4d6;心灵鸡汤&#x1f4d6;社会不相信庸俗&#xff0c;成功需要汗水和寂寞铸就。无数次的质疑或是嘲笑&#xff0c;这些都无所谓&#xff0c;记住自己是谁&#xff0c;自己想要什么就…

Django的信号机制解读

Django的信号 Django的信号机制不同于Linux的信号机制&#xff0c;Django 中的信号用于在框架执行操作时解耦。当某些动作发生的时候&#xff0c;系统会根据信号定义的函数执行相应的操作 Django的信号主要包含以下三个要素&#xff1a; 发送者&#xff08;sender&#xff0…

网络隔离后的文件传输怎么解决?深度解析4种主流方案

网络隔离对于很多企业来说并不陌生&#xff0c;出于数据安全的考虑&#xff0c;为了隔离有害的网络和可能的网络攻击&#xff0c;越来越多的企业在内部进行了网络隔离。隔离的形态和方式有多种&#xff0c;总体上主要以物理隔离和逻辑隔离为主。网络隔离可以一定程度上甚至彻底…

功能测试环境搭建

前言新年好呀大家&#xff0c;大家都复工了吗~小编已经在搬砖中了&#x1f636;在假期中小编学习了一点功能测试方面知识&#xff0c;打算写篇博客记录下来&#xff0c;希望这篇博客可以帮到需要的朋友。流程图一、测试计划测试计划需要在所有的测试工作之前进行&#xff0c;一…

HTTP协议(2)

1)当我们在浏览器上面输入一个搜狗搜索的网址之后&#xff0c;浏览器就会给搜狗的服务器发送了一个HTTP请求&#xff0c;这样咱们的搜狗的服务器就会返回一个HTTP响应&#xff1b; 2)当这个响应结果被浏览器解析之后&#xff0c;就展示成了我们目前所看到的页面内容&#xff0c…

20230203英语学习

What Is a Dog Anyway? 狗的争议性起源&#xff1a;到底怎么定义“狗” The geographer Jared Diamond has called domestication the worst mistake humans ever made. And yet, the first domestication — the turning of wolves into dogs — was an impressive feat.Hu…

java对象的比较

上一章中关于PriorityQueue的使用要注意&#xff1a; 1. PriorityQueue中放置的元素必须要能够比较大小&#xff0c;不能插入无法比较大小的对象&#xff0c;否则会抛出 ClassCastException异常 2. 不能插入null对象&#xff0c;否则会抛出NullPointerException 3. 没有容量限制…

C/C++ 内存泄漏检测

C/C 内存泄漏检测内存泄漏的两个问题使用宏定义覆盖 malloc 和 free 函数使用 hook 钩子最近学习了 C/C 内存泄漏检测的相关知识&#xff0c;写博客记录一下。 内存泄漏的两个问题 是否有内存泄漏&#xff1f;内存泄漏是在代码的哪一行&#xff1f; 检测内存泄漏主要从上面两…

数据库系统概念 | 第十三章:事务管理 | 事务特性(ACID)| 冲突可串行化

文章目录&#x1f4da;事务的概念&#x1f407;事务定义&#x1f407;事务界定&#x1f407;事务特性&#xff08;ACID&#xff09;&#x1f407;一个简单的事务模型&#x1f4da;存储器结构&#x1f4da;事务的原子性和持久性&#x1f407;几种常见的事务状态&#x1f407;事务…

MDA260-16-ASEMI整流模块MDA260-16

编辑-Z MDA260-16在MDA封装里采用的2个芯片&#xff0c;是一款单臂共阳极整流模块。MDA260-16的浪涌电流Ifsm为11000A&#xff0c;漏电流(Ir)为15mA&#xff0c;其工作时耐温度范围为-40~150摄氏度。MDA260-16采用GPP硅芯片材质&#xff0c;里面有2颗芯片组成。MDA260-16的电性…

转行大数据开发应该怎么学习

转行进入大数据&#xff0c;首先需要了解的就是大数据是做什么&#xff0c;工作内容&#xff0c;然后就是找个完整的学习路线跟着去学习了&#xff0c;大数据的学习内容也是不少的~ 简单来说&#xff0c;分为6步&#xff0c;大数据开发入门&#xff0c;大数据核心基础&#xf…

【iHooya】2023年2月2日寒假作业解析

#include <bits/stdc.h> using namespace std;int main() {int n, r; //n个人&#xff0c;r个水龙头cin >> n >> r;int time[n];for (int a 0; a < n; a){cin >> time[a];}sort(time, time n); //时间从小到大排序int minx 0, lt_time[10001], j…

程序全过程:觉醒(序)

程序全过程序很惭愧&#xff0c;写了几年的程序&#xff0c;技术的功力没有太大增长&#xff0c;只是在项目的熟悉程度上有不少进步。因为上学时没好好学&#xff0c;很多现在工作中用到的编程技能都是在工作中边学边用的&#xff0c;相当于一直处于临时抱佛脚的状态&#xff0…

iptables端口复用

环境&#xff1a; 攻击主机&#xff1a;Kali -- 192.168.218.135 目标主机&#xff1a;RHEL8 -- 192.168.218.129 什么是端口复用 端口复用是指不同的应用程序使用相同端口使用相同端口进行通讯。 场景 目标主机是Linux系统&#xff0c;目标主机防火墙有严格的限制&#…

【FAQ】申请运动健康服务验证环节常见问题及解答

华为 HMS Core 运动健康服务&#xff08;HUAWEI Health Kit&#xff09;提供原子化数据开放。应用在获取用户数据授权后&#xff0c;可通过接口访问运动健康数据&#xff0c;对用户数据进行读写等操作&#xff0c;为用户提供运动健康类数据服务。 开发者应用在开发和测试阶段访…