IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> mysql分页的sql性能优化 -> 正文阅读

[大数据]mysql分页的sql性能优化

背景:因为公司的报表需求,需要批量统计数千万数据,单个sql无法满足使用场景,于是分页将数据查询出来并进行处理。

- 采用传统分页

        return  lambdaQuery().le(GuOrder::getGuaranteeStartDate,date)
                .select(GuOrder::*,
                        GuOrder::*,
                        GuOrder::*,
                        GuOrder::*,
                        GuOrder::*,
                        GuOrder::*)
                .page(new Page<>(pageNum, pageSize,false)).getRecords();
.............省略
耗时:1567,数量:5000 
耗时:1868,数量:5000 
耗时:1976,数量:5000 
耗时:2527,数量:5000 
耗时:2927,数量:5000 
耗时:3539,数量:5000 
耗时:4539,数量:5000 
耗时:4963,数量:5000 
耗时:5509,数量:5000 
耗时:5544,数量:5000 
  • 测试数据量共70w,我们可以看到查到最后非常缓慢,这里分页时,索引需要翻页,查询的页越往后,翻的页越多,导致越来越慢。

  • 由于项目使用了主键自增,所以想到用当前页的最大Id来进行分页

- 采用主键自增id分页

踩坑:LIMIT #{pageNum},
在这里插入图片描述

由于id并非完全按照主键自增排序的(参考上一篇文章),此处id会出现跳过数据的情况,我们发现这里第一条数据,竟然从1139559开始

我们将子查询id进行order by和主查询都order by
在这里插入图片描述
终于拿到了我们想要的值
但大部分情况我们是需要条件的,于是

select
 *
from
  vc_gu_order
where
  id >= (
    SELECT
      a.id
    FROM
      vc_gu a
    WHERE
      a.is_deleted = 0
      AND a.date between '2022-05-01' and '2022-05-31'
      order by id
    LIMIT
      5000, 1
  )
  and a.date between '2022-05-01' and '2022-05-31'
limit
  5000;

我们可以看到如果这样查询需要主查询和子查询都需要走一次索引,而date是非聚簇索引,这样查询数据又要多回表2次
查询耗时,也会多了许多在这里插入图片描述
继续改造,怎么能少走一次索引,根据上面Sql我们发现,翻页时,如果要查询的id符合顺序,next页码的值=页码+页数,如果要查询的值得总id范围=1,10000,那么最小id一定是1,最大id一定是10000,那我们可不可以在1,10000中进行分页查询呢?这样我们只需要求一次最小id和最大id即可

    SELECT
    max(id) as maxId,
    min(id) as minId FROM table where date BETWEEN '2022-05-01' AND '2022-05-31'

最大id8080261 最小id7392515
根据最小id和最大查询id查询分页

select
 *
from
  table 
where
  id > 7397515
  and date BETWEEN '2022-05-01' AND '2022-05-31' ORDER BY id
limit
  5000;

在这里插入图片描述
我们可以看到这个id在700w数据之后,查询的效率提升了却很多倍,有人问最大id不是已经查出来了,为什么不直接id between min and max,这个问题,还是和一开始一样,id和date其实是不连续的,即使某个id符合最大最小的id范围,但是id依然不属于这个date范围。

附分页代码

        Integer pageSize = 5000;
        MaxAndMinIdDTO maxAndMinId = guService.getMaxAndMinId(date);
        if (Objects.isNull(maxAndMinId)){
            return new ArrayList<>();
        }
        Long minId = maxAndMinId.getMinId();
        Long maxId = maxAndMinId.getMaxId();
        if (maxAndMinId.getMinId()==null){
            return new ArrayList<>();
        }
        minId = minId-1;
        List<GU> gu;
        List<GU> gus= new ArrayList<>();
        boolean flag;
        do{
            gus= guService.pageBeforeDate(date, minId, pageSize);
            if (CollUtil.isNotEmpty(gus)){
            }
            minId = guOrders.get(guOrders.size()-1).getId();
            flag = maxId > minId;
        }while (flag);
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:22:42  更:2022-09-13 11:23:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:43:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码