跨库分页查询

news2024/12/26 23:37:24

背景

随着数据量的增大,数据库需要进行水平切分,例如通过业务主键id取模,使得数据均匀分布到不同的库中,随之而来的问题就出现跨库如何进行分页查询。

举例

select * from t_user order by time offset 200 limit 100

当在单库单表进行查询的时候,是拥有全局视野的,当进行了水平切分后,就失去了全局视野,数据按照time局部排序之后,不管哪个分库的第3页数据,都不一定是全局排序的第3页数据。 

全局视野法

由于失去了全局视野,怎么重新获取全局视野呢,每个库都返回3页数据,所得到的数据在服务层进行内存排序,得到数据全局视野,再取第3页数据,便能够得到想要的全局分页数据。

步骤:

  1. 将order by time offset X limit Y,改写成order by time offset 0 limit X+Y
  2. 服务层将改写后的SQL语句发往各个分库:即例子中的各取3页数据
  3. 假设共分为N个库,服务层将得到N*(X+Y)条数据:即例子中的6页数据
  4. 服务层对得到的N*(X+Y)条数据进行内存排序,内存排序后再取偏移量X后的Y条记录,就是全局视野所需的一页数据

方案优点:通过服务层修改SQL语句,扩大数据召回量,能够得到全局视野,业务无损,精准返回所需数据。

方案缺点

  1. 每个分库需要返回更多的数据,增大了网络传输量(耗网络);
  2. 除了数据库按照time进行排序,服务层还需要进行二次排序,增大了服务层的计算量(耗CPU);
  3. 最致命的,这个算法随着页码的增大,性能会急剧下降,这是因为SQL改写后每个分库要返回X+Y行数据:返回第3页,offset中的X=200;假如要返回第100页,offset中的X=9900,即每个分库要返回100页数据,数据量和排序量都将大增,性能平方级下降。

业务折中法

全局视野法虽然深分页时候性能较差,但是返回数据准确,有没有性能更优的方案呢,业务需求的折中能够极大的简化技术方案。

业务折中-禁止跳页查询

在数据量很大,翻页数很多的时候,很多产品并不提供“直接跳到指定页面”的功能,而只提供“下一页”的功能,这一个小小的业务折衷,就能极大的降低技术方案的复杂度。

  1. 将查询order by time offset 0 limit 100,改写成order by time where time>0 limit 100
  2. 上述改写和offset 0 limit 100的效果相同,都是每个分库返回了一页数据
  3. 服务层得到2页数据,内存排序,取出前100条数据,作为最终的第一页数据,这个全局的第一页数据,一般来说每个分库都包含一部分数据
  4. 点击“下一页”时,需要拉取第二页数据,在第一页数据的基础之上,能够找到第一页数据time的最大值,将查询order by time offset 100 limit 100,改写成order by time where time>$time_max limit 100,这下不是返回2页数据了(“全局视野法,会改写成offset 0 limit 200”),每个分库还是返回一页数据
  5. 服务层得到2页数据,内存排序,取出前100条数据,作为最终的第2页数据,这个全局的第2页数据,一般来说也是每个分库都包含一部分数据,如此往复,查询全局视野第100页数据时,不是将查询条件改写为offset 0 limit 9900+100(返回100页数据),而是改写为time>$time_max99 limit 100(仍返回一页数据),以保证数据的传输量和排序的数据量不会随着不断翻页而导致性能下降。

业务折中-允许数据精度损失

全局视野法能够返回业务无损的精确数据,在查询页数较大,例如第100页时,会有性能问题,如果业务上面能够接收返回数据不是那么精准,允许有一些数据偏差,那么可以大大减少技术的实现难度。

例如使用业务主键id取模,理论上在各个分库上的数据分布,统计概率情况是一致的。

利用这一原理,要查询全局100页数据,offset 9900 limit 100改写为offset 4950 limit 50,每个分库偏移4950(一半),获取50条数据(半页),得到的数据集的并集,基本能够认为,是全局数据的offset 9900 limit 100的数据,当然,这一页数据的精度,并不是精准的。

总结:业务折中法需要需求上面进行相应让步,可以搭配上各种搜索条件,能够提高相应精度,也是可以满足多数场景的。

二次查询法

二次查询法能够满足业务的精确需要,无需业务折中,又高性能的方法。

为了方便举例,假设一页只有5条数据,查询第200页的SQL语句为select * from T order by time offset 1000 limit 5

步骤一:查询改写

将select * from T order by time offset 1000 limit 5

改写为select * from T order by time offset 500 limit 5

并投递给所有的分库,注意,这个offset的500,来自于全局offset的总偏移量1000,除以水平切分数据库个数2。

如果是3个分库,则可以改写为select * from T order by time offset 333 limit 5

假设这三个分库返回的数据(time, uid)如下:

可以看到,每个分库都是返回的按照time排序的一页数据。 

步骤二:找到所返回3页全部数据的最小值

第一个库,5条数据的time最小值是1487501123

第二个库,5条数据的time最小值是1487501133

第三个库,5条数据的time最小值是1487501143

 故,三页数据中,time最小值来自第一个库,time_min=1487501123,这个过程只需要比较各个分库第一条数据,时间复杂度很低

步骤三:查询二次改写

第一次改写的SQL语句是select * from T order by time offset 333 limit 5

第二次要改写成一个between语句,between的起点是time_min,between的终点是原来每个分库各自返回数据的最大值:

第一个分库,第一次返回数据的最大值是1487501523

所以查询改写为select * from T order by time where time between time_min and 1487501523

第二个分库,第一次返回数据的最大值是1487501323

所以查询改写为select * from T order by time where time between time_min and 1487501323

第三个分库,第一次返回数据的最大值是1487501553

所以查询改写为select * from T order by time where time between time_min and 1487501553

相对第一次查询,第二次查询条件放宽了,故第二次查询会返回比第一次查询结果集更多的数据,假设这三个分库返回的数据(time, uid)如下:

可以看到:

由于time_min来自原来的分库一,所以分库一的返回结果集和第一次查询相同(所以其实这次访问是可以省略的);

分库二的结果集,比第一次多返回了1条数据,头部的1条记录(time最小的记录)是新的(上图中粉色记录);

分库三的结果集,比第一次多返回了2条数据,头部的2条记录(time最小的2条记录)是新的(上图中粉色记录);

步骤四:在每个结果集中虚拟一个time_min记录,找到time_min在全局的offset

在第一个库中,time_min在第一个库的offset是333

在第二个库中,(1487501133, uid_aa)的offset是333(根据第一次查询条件得出的),故虚拟time_min在第二个库的offset是331

在第三个库中,(1487501143, uid_aaa)的offset是333(根据第一次查询条件得出的),故虚拟time_min在第三个库的offset是330

综上,time_min在全局的offset是333+331+330=994

步骤五:既然得到了time_min在全局的offset,就相当于有了全局视野,根据第二次的结果集,就能够得到全局offset 1000 limit 5的记录

第二次查询在各个分库返回的结果集是有序的,又知道了time_min在全局的offset是994,一路排下来,容易知道全局offset 1000 limit 5的一页记录(上图中黄色记录)。

这种方法的优点是:可以精确的返回业务所需数据,每次返回的数据量都非常小,不会随着翻页增加数据的返回量。

不足是:需要进行两次数据库查询,实现复杂。

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

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

相关文章

NXP i.MX 6ULL工业核心板规格书( ARM Cortex-A7,主频792MHz)

1 核心板简介 创龙科技SOM-TLIMX6U是一款基于NXP i.MX 6ULL的ARM Cortex-A7高性能低功耗处理器设计的低成本工业级核心板,主频792MHz,通过邮票孔连接方式引出Ethernet、UART、CAN、LCD、USB等接口。核心板经过专业的PCB Layout和高低温测试验证&#xf…

Jenkins在Ubuntu的安装问题

使用apt安装没有成功,各种报错。最后使用了离线安装方式。 1、安装jdk。和之前的安装jdk无异,增加一步 添加一个软链接 sudo ln -s /path/to/java/home/bin/java /usr/bin/java 2、下载deb包,然后安装 2.1、前置步骤,安装可能…

面向适航符合性的智能航电系统认证研究进展

摘要 民用飞机航电系统引入人工智能/机器学习技术会带来可信性、不确定性和可解释性等问题,有必要通过有效的符合性方法向公众与利益攸关方证实智能航电系统的适航安全性。首先,分析了智能航电系统的等级分类和应用现状,阐述了现有指南和标准…

three.js通过CubeTexture加载环境贴图,和RGBELoader加载器加载hdr环境贴图

一、使用CubeTexture进行环境贴图 1.CubeTexture使用介绍 Three.js中可以通过使用CubeTexture进行环境贴图,CubeTexture需要将6张图片(正面、反面、上下左右)包装成一个立方体纹理。下面是一个简单的例子: 首先需要加载六张贴图…

关于随机梯度下降算法及其改进方向

回归与分类等监督学习是机器学习中最常见的一类学习问题, 它提供了包含输入数据和目标数据的训练数据集。为了探讨输入与目标之间的关系,需要先建立含参数的表示模型,再通过最小化所有样本的平均损失函数来获得最优的参数, 此处的优化模型通常为经验风险…

【SpringMVC】统一异常处理 前后台协议联调 拦截器

1,统一异常处理 1. 问题描述 在讲解这一部分知识点之前,我们先来演示个效果,修改BookController类的getById方法 GetMapping("/{id}") public Result getById(PathVariable Integer id) {//手动添加一个错误信息if(id1){int i …

那些曾经考过的turtle绘图题(16~20)

【编程实现绘图 -16】 使用turtle绘制如右图1中所示的图形。 上边是一个红色轮廓、黄色填充的边长为300的等边三角形,下边是一个绿色填充、半径为150的半圆。 要求: 1)画布背景为白色,等边三角形为红色轮廓、黄色填充; 2)半圆为绿色填充、且与等边三角形在底边的中点处相…

OpenCV——总结《车牌识别》之《常用的函数介绍》

1. cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))element cv2.getStructuringElement(shape, ksize[, anchor])用于创建形态学操作的结构元素(structuring element)。 参数解释: shape:结构元素的形状,可以…

k近邻算法

文章目录 一、K近邻算法(K Nearest Neighbor algorithm, KNN)1.概念2.流程3.问题——不能用来图像分类1)图像分类2)为什么不能用来图像分类3)数据库样例:CIFAR-10 二、HEU的K近邻算法1.概念2.伪代码3.k近邻算法是非线性分类算法4.…

java项目之教学视频点播系统ssm

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的教学视频点播系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 💕💕作者:风歌&…

SVM支持向量机理解_KKT条件_拉格朗日对偶_SMO算法代码

目录 一、支持向量机基本型(线性可分) 1.1 问题描述 1.2 参考资料 二、KKT条件 2.1 KKT条件的几个部分 2.1.1 原始条件 2.1.2 梯度条件 2.1.3 松弛互补条件 2.1.4 KKT条件小结 2.2 参考资料 三、对偶形式 3.1 由原始问题到对偶问题 3.2 对偶…

ubuntu双系统安装

1. 下载系统 国内镜像 http://mirrors.ustc.edu.cn/ubuntu-releases/2. U盘启动盘 Rufus 软件 制作U盘启动盘 Rufus 链接 https://rufus.en.softonic.com/3. 磁盘中准备一定未分配磁盘 我准备了100G 4. BIOS启动项选择为usb启动(每个品牌进BIOS不同&#xff0…

win下 Nginx.conf 路径配置注意事项(win)

win下 Nginx.conf 路径配置注意事项 文章目录 可使用win绝对路径路径不能包含中文路径不能包含空格路径中的"\n"会被识别成换行贴一段正确配置的Nginx.conf代码 可使用win绝对路径 网上有种说法是win下Nginx不能设置绝对路径,但我在Nginx-1.24.0下是设置…

在Windows11中安装WSL2(Ubuntu20.04)并配置Anaconda环境

在Windows11中安装WSL2(Ubuntu20.04)并配置Anaconda环境 文章目录 在Windows11中安装WSL2(Ubuntu20.04)并配置Anaconda环境说在前面1. 检查开启CPU虚拟化和虚拟机平台2. 安装Ubuntu20.043. Vscode连接WSL2(Ubuntu20.04)4. Anaconda开发环境的搭建5. Vscode 访问 notebook结尾 说…

高效视觉识别的动态感知器

文章目录 Dynamic Perceiver for Efficient Visual Recognition摘要本文方法实验结果 Dynamic Perceiver for Efficient Visual Recognition 摘要 Early exiting已成为提高深度网络推理效率的一种很有前途的方法。通过构建具有多个分类器(出口)的模型,可以在较早的…

佩戴舒适的蓝牙耳机有哪些?公认佩戴舒适性不错的蓝牙耳机推荐

​都2023年了,不会还有人没有一款蓝牙耳机吧?随着蓝牙耳机的增长,越来越多人不知道如何挑选蓝牙耳机了,蓝牙耳机除了音质表现要好之外,还有就是佩戴舒适性不能差,防水性能要有,接下来&#xff0…

WPF 的几种模板概念

WPF中有三大模板ControlTemplate,ItemsPanelTemplate,DataTemplate.其中ControlTemplate和ItemsPanelTemplate是控件模板,DataTemplate是数据模板,他们都派生自FrameworkTemplate抽象类。 看看如下继承图: ControlTemplate <Style TargetType="Button">&…

MiniGPT-4 模型学习与实战

1 前言 MiniGPT-4 是一个冻结的视觉编码器(Q-Former&ViT)与一个冻结的 文本生成大模型&#xff08;Vicuna&#xff0c;江湖人称&#xff1a;小羊驼&#xff09; 进行对齐造出来的。 MiniGPT-4 具有许多类似于 GPT-4 的能力, 图像描述生成、从手写草稿创建网站等MiniGPT-4…

bitbucket 配置 SSH keys

目录 问题 配置方法 生成SSH key 添加SSH key至SSH Agent 添加公钥至Bitbucket 执行Git clone 问题 拉取bitbucket上的代码需要配置SSH key Configure SSH and two-step verification | Bitbucket Cloud | Atlassian Support 以Linux为例&#xff1a; Set up persona…

WebSocket 的介绍及基本使用

websocket 什么是 websocket ? https://websocket.org/ 是一种网络通信协议&#xff0c;和 HTTP 协议 一样。 为什么需要websocket ? 因为 HTTP 协议有一个缺陷&#xff1a;通信只能由客户端发起。 了解 websocket api含义 基于原生的 websocket 完成服务端和客户端的通…