Cobar提出的一种在分库场景下对Order By / Limit 的优化「终于解决」

Cobar提出的一种在分库场景下对Order By / Limit 的优化「终于解决」搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。 本文已收录 https://github.com/lkxiaolou/lkxiao

Cobar提出的一种在分库场景下对Order By / Limit 的优化

搜索关注微信公众号”捉虫大师”,后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。

Cobar 虽然是一款“古老”的数据库中间件,但目前不少公司仍然在用它,且它包含了不少有意思的算法和实现,今天就来分享 Cobar 提出的一种在分库场景下对 Order By / Limit 的优化。

原算法描述参考: https://github.com/alibaba/cobar/blob/master/doc/cobarSolution.ppt

背景

Cobar 最重要的功能就是分库分表,通常读取性能瓶颈可以通过增加从库或缓存来解决。

但写入性能在 MySQL 上只能通过分库分表来提升。

当我们把数据分布到不同的数据库上时,再查询时如果是单条数据只要找到这条数据对应的库即可,但如果是多条数据,可能分布在不同的库上时,Cobar 就需要先查询,再聚合。
image

来个具体例子:

image

如果我们要查询 tb1 表的 c1 字段,且取 c1 正序的下标(从0开始)为4、5的数据。假设分了三个库,我们为了取到正确数据,需要去这三个分库都取下标0-5的数据,假设取到如下数据:

image

取到3堆已排序的数据,对这3堆数据从小开始丢弃0、1、2、3号数据,保留第4、5号数据即是我们需要的。

image

这个算法看起来没啥问题,但如果数据量稍微变化一下,比如:

select c1 from tb1 order by c1 limit 9999999, 4

如果还按照上述的方法来做,首先得去每个分库查询 0 – 10000003的数据,然后再合并丢弃0-9999998号数据。

相当于丢弃了大约不分库时3倍的数据。这多少显得有点浪费了。

算法优化

  • Step1:将这条语句拆分成3条语句发给3个分库:

image

  • Step2:找出查询结果的最大和最小值,这里假设最小值为3,最大值为11

image

  • Step3:以最小值和最大值为条件再次查询

image

假设我们取得的数据如图,那么我们是不是很容易推断出这些结果之前还有多少数据?

  • Step4:反查出每一个返回结果的 offset,这里我们就能推断出分库1在最小值之前还有3333332条数据,分库2在最小值之前还有3333333条数据,分库3在最小值之前还有3333331条数据

image

这时,我们就可以丢弃合并后的0-9999998号数据了,分库1、2、3将最小值之前的数据都丢弃共丢弃了0-9999995号数据,再丢弃3个最小值3刚好够到了9999998,所以9999999号数据开始依次是4、5、5、6

image

算法分析

效率

以上例来说明,未优化前:

  • 1次查询,查询的数据总量大约 3kw,丢弃9999999条数据

优化后:

  • 第1次查询,查询数据总量约 1kw
  • 第2次查询,数据总量17
  • 丢弃3条数据

从这个例子可以看出,查询的数据量大大减少,需要计算丢弃的量也大大减少

非理想情况

可能大家能看出来,上述例子是非常理想的情况,如果数据没这么“理想”,结局又是怎样?

  • Step4 中反查的最小值之前不够丢弃怎么办,比如:

image

  • Step4 中反查的最小值之前的数据比需要丢弃的数据多怎么办?

image

可以看出,如果是这两种情况,这种算法就没法再次生效了。

优化的前提

根据上述两种情况来看,可以总结出该算法生效的前提是:

数据(排序字段)在各个分库上的分布要均匀

其实可以做个极端的假设,比如只有第一个分库上有数据,其他数据库没有数据,那么这个算法就失效了

总结

这么来看,这个算法是不是很废?确实比较废,就连 Cobar 中也没有使用。

但在某些场景下还是有比较大的提升的,分库的数据大部分时候是按字段进行取模,所以可以认为几乎是分布均匀的,此时如果 Order By / Limit 是比较深度翻页的数据,可以采取此策略,但也要进行兜底,如果返回的数据不满足条件,继续退化为最初的算法,所以单次效率可能不高,但从统计值上来看其效率可能是更高的。


搜索关注微信公众号”捉虫大师”,后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。

image

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/5789.html

(0)
上一篇 2023-04-24
下一篇 2023-04-24

相关推荐

  • mysql在win下移植

    mysql在win下移植 背景:由于电脑太多垃圾了,重装了系统;但是mysql又不想重装,里面的数据还有用 步骤 把原来的MySQL安装文件压缩,如: mysql-8.0.11-winx64-back.zip 通过u…

    2023-02-25
    146
  • Python变量类型判断方法介绍

    Python变量类型判断方法介绍Python是一种动态语言,不要求在变量定义时指定数据类型。Python能够自动根据变量的值来推断出变量的类型。

    2024-08-29
    23
  • Python元组:不可变序列容器

    Python元组:不可变序列容器Python是一种高级编程语言,它具有简单易学、可读性强、高效等优点。在Python中,数据类型包括数字、字符串、列表、元组、集合和字典等。本文将对元组(tuple)这种数据类型进行详细的讲解。

    h3一、元组的定义和基本操作/h3

    p元组是Python中的一种不可变序列容器,用逗号隔开若干个数据项(可以是任意数据类型),并使用小括号进行包裹即可。元组中的数据可以通过下标进行访问,也可以通过切片进行操作。元组一旦创建后,就不能再进行修改,因此可以实现常量级别的数据存储和传递。示例代码如下:

    2024-02-05
    98
  • TiDB 在马上消费金融核心账务系统归档及跑批业务下的实践「建议收藏」

    TiDB 在马上消费金融核心账务系统归档及跑批业务下的实践「建议收藏」作者介绍: 康文权,马上消费金融总账高级研发工程师。 李银龙,原腾讯云运维工程师,马上消费金融容器云 TiDB 负责人,西南区 TUG Leader。 背景介绍 马上消费金融于 2015 年 6 月…

    2023-01-27
    127
  • 袋鼠云app_袋鼠查

    袋鼠云app_袋鼠查不知不觉间,2022年的脚步已经走到了倒数第二个月。临近年末,我们对产品本身以及客户反馈的一些问题进行了持续的更新和优化,例如基线告警、数据服务平台新增TDengine 数据源支持、行级权限根据用户属

    2023-06-14
    144
  • Python字典.items()方法,快速获取键值对!

    Python字典.items()方法,快速获取键值对!Python字典是一种键-值对数据结构,其中每个键都有对应的值。通常情况下,字典的键是唯一的,而值则可以是任何数据类型。Python中的字典类提供了许多实用的方法,其中包括.items()方法,该方法可以让我们快速获取字典的键值对。.items()方法返回一个代表字典中所有键值对的列表,其中每个元素本身就是一个由键值组成的元组。以下是.items()方法的基本语法:

    2024-02-26
    102
  • NoSql非关系型数据库之MongoDB应用(一):安装MongoDB服务 – 熊泽「终于解决」

    NoSql非关系型数据库之MongoDB应用(一):安装MongoDB服务 – 熊泽「终于解决」业精于勤,荒于嬉;行成于思,毁于随。 一、MongoDB服务下载安装(windows环境安装) 1.进入官网:https://www.mongodb.com/,点击右上角的 Try Free , 2.

    2023-04-18
    161
  • 用户画像系统架构——从零开始搭建实时用户画像(二)「终于解决」

    用户画像系统架构——从零开始搭建实时用户画像(二)「终于解决」​ ​ 在《 "什么的是用户画像" 》一文中,我们已经知道用户画像对于企业的巨大意义,当然也有着非常大实时难度。那么在用户画像的系统架构中都有哪些难度和重点要考虑的问题呢? 挑战

    2023-03-04
    144

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注