一亿数据大表,我们是如何做分页的

公众号:Hoeller,有精品面试题(不是很多,150道,但很经典)

本文是基于我们公司的情况做的大表分页方案简单记录,不一定适合所有业务场景,大家感兴趣的读一下,可以在评论区讨论,技术交流,文明用语。

最近在做一个功能,有一张大概一亿的数据需要做分页查询,所以存在深分页的问题,也就是越靠后的页访问起来就会越慢,所以需要对这个功能进行优化。

对于深分页问题,一般都是采用传递主键ID的做法来解决,也就是每次查询下一页数据时,把上一页数据中最大的ID传递给下一页,这样在查询某一页时就能利用主键索引来快速查询了。

但是由于历史原因,那张一亿数据的大表没有主键ID,-_-,所以这是需要解决的问题之一。

另外,就算能利用主键索引快速查询分页数据,但是毕竟是一亿数据,最终查询比较靠后的页数时,因为数据量大就算走索引最后还是会比较慢,所以就需要分表了。

我们先使用SQL脚本的方式把一亿数据迁移到分表,我们按照时间季度进行分表,比如2022q1、2022q2、2023q1这种方式来进行分表,这样每张分表的数据就不会太多了,大概1000万左右,并且在创建分表时顺便给分表添加主键ID字段,然后在迁移数据时需要按照原始大表的交易时间进行升序排序,保证ID的自增顺序与交易时间顺序是一致的。

不过这种方案存在两个问题,第一个问题就是查询分页时跨分表了怎么办,比如我查第10页数据时,一部分数据在2023q1,一部分数据在2023q2,首先在查询时本身就需要选择年份和季度,所以直接就确定了对应的是哪张分表,查询时根据年份和季度直接定位到分表,然后再进行分页查询,所以不会出现跨表,这个问题就自然而然解决了。

另外,每张表的主键ID要不要连续,比如2022q1的主键是1-1000000,那么2022q1的主键要不要是1000001-2000000,其实我个人觉得需要这么设计,因为两个分表的数据逻辑上其实一张表,所以主键最好不冲突,但是考虑到实现难度,暂时没有采取,而是每张分表的主键ID都是从1开始的,这种方案在目前看来是没有问题的,因为每次都只会从一张分表中查询数据,不会出现跨表的情况。

另外,在设计时也想到过能不能直接用交易时间做为主键来进行分表,但是想到交易时间的精度是秒,所以很有可能出现交易时间相同的记录,这样在做分页时可能会出现下一页数据和上一页数据有重复的,所以还是需要单独设计一个主键ID。

继续思考,假如这张一亿数据的大表要做分页,但是不根据年份和季度做查询来分页,而就是直接分页,那又该如何呢?

首先,肯定还是得利用分表和主键索引,我的思路是,先给原始表添加主键ID并生成自增ID,然后再按主键ID进行分表,分表记录数也可以控制在1000万左右,前端查询时仍然按ID来查分页就可以了,但是此时就存在跨表的问题,比如每页如果是20条,查第10页数据时,如果从分表一只查出了5条,那么后端接口判断5小于20,就尝试从分表二中继续查。

当然了,如果既有复杂的查询条件,又需要进行分页,那用关系型数据库就不太好做了,就可以考虑ES之类的了。

大家有什么更好的经验或思路,欢迎不吝赐教。

我是爱分享技术的大都督周瑜,欢迎关注我的公众号:Hoeller。公众号里有更多高质量干货系列文章和精品面试题。

记得点赞、分享哦!!!

相关推荐
阿伟*rui2 小时前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
XiaoLeisj3 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck4 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei4 小时前
java的类加载机制的学习
java·学习
码农小旋风5 小时前
详解K8S--声明式API
后端
Peter_chq5 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml45 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~5 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616886 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7896 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot