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

本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。

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

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

背景

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

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

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

来个具体例子:

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

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

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

select c1 from tb1 order by c1 limit 9999999, 4

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

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

算法优化

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

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

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

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

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

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

算法分析

效率

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

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

优化后:

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

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

非理想情况

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

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

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

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

优化的前提

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

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

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

总结

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

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


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

Cobar提出的一种在分库场景下对Order By / Limit 的优化的更多相关文章

  1. Ironic几种不同的场景下的网络拓扑

    最近帮领导做了几页ppt,总结几种场景下ironic管理物理机网络的网络拓扑,简单做成一份文章记录下.只是方便自己记忆,没有认真修改.如果对ironic有一定了解,可以看下,加深理解. 1. vlan ...

  2. C++高并发场景下读多写少的优化方案

    概述 一谈到高并发的优化方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也能很大的影响整体性能,本文从单模块下读 ...

  3. 超大规模商用 K8s 场景下,阿里巴巴如何动态解决容器资源的按需分配问题?

    作者 | 张晓宇(衷源)  阿里云容器平台技术专家 关注『阿里巴巴云原生』公众号,回复关键词"1010",可获取本文 PPT. 导读:资源利用率一直是很多平台管理和研发人员关心的话 ...

  4. Redis11种Web应用场景

    Redis的一个非常大优点就是能够不用整个转入到这个数据库,而是能够沿用之前的MySQL等数据库,而仅在一些特定的应用场景通过Redis的特性提高效率.本文列出了11个这种Web应用场景,如显示最新的 ...

  5. Redis 11种Web应用场景举例

    在"怎样让redis在你的系统中发挥作用"一文中,salvatore 'antirez' sanfilippo告诉我们如何利用redis独有的数据结构处理能力来解决一些常见问题.一 ...

  6. Redis能干啥?细看11种Web应用场景

    下面列出11种Web应用场景,在这些场景下可以充分的利用Redis的特性,大大提高效率. 1.在主页中显示最新的项目列表. Redis使用的是常驻内存的缓存,速度非常快.LPUSH用来插入一个内容ID ...

  7. Redis能干啥?细看11种Web应用场景[转]

    下面列出11种Web应用场景,在这些场景下可以充分的利用Redis的特性,大大提高效率. 1.在主页中显示最新的项目列表. Redis使用的是常驻内存的缓存,速度非常快.LPUSH用来插入一个内容ID ...

  8. Gartner提出的7种多租户模型

    下面,我们就来看看在SaaS应用搭建过程中,可以采用什么样的多租户模型.从而能较为清晰地了解未来使用PaaS平台开发的SaaS,可以为用户提供哪些多租户的服务.        Gartner提出了7种 ...

  9. SSD固态盘应用于Ceph集群的四种典型使用场景

    在虚拟化及云计算技术大规模应用于企业数据中心的科技潮流中,存储性能无疑是企业核心应用是否虚拟化.云化的关键指标之一.传统的做法是升级存储设备,但这没解决根本问题,性能和容量不能兼顾,并且解决不好设备利 ...

随机推荐

  1. Js/jquery常用

    id属性不能有空格 1. js判断checkebox是否被选中 var ischecked = document.getElementById("xxx").checked  // ...

  2. python pip/anaconda使用笔记

    Switch to Chinese conda Source, config file is in ~/.condarc conda config --add channels https://mir ...

  3. introduction-to-64-bit-assembly

    introduction-to-64-bit-assembly NASM - The Netwide Assembler x86-64 下函数调用及栈帧原理 汇编语言基本概念简介 mycode

  4. Redis-技术专区-让你彻底会使用“Redis中最陌生且最强大的集合”(ZSET)【前篇】

    前言介绍 很多小伙伴都跟我说,redis中,ZSet(有序集合)是他们最陌生的集合,同时也是觉得特别复杂的集合之一,在开发过程中经常会用到它,而且也是大家最不太有把握使用的集合,所以笔者就从ZSet集 ...

  5. 哲学家就餐问题-Java语言实现死锁避免

    哲学家就餐问题-Java语言实现死锁避免 我死锁预防是至少破坏死锁产生的四个必要条件之一,带来的问题就是系统资源利用率低且不符合开发习惯,而死锁避免不是事先釆取某种限制措施破坏死锁的必要条件,只是注意 ...

  6. junit5 yaml和json 数据驱动

    使用yaml 数据驱动测试 新建用例数据类,用于动态修改测试数据 对应yaml文件,第一层结构为列表 第二层结构为具体序列化class对象 测试成功 public class TestYaml { @ ...

  7. 从需求去理解 Linux dbus与基于dbus协议的无agent软件管理

    What is IPC IPC [Inter-Process Communication] 进程间通信,指至少两个进程或线程间传送数据或信号的一些技术或方法.在Linux/Unix中,提供了许多IPC ...

  8. JS008. 跳转缓存滚动条高度并返回时过渡动画(window.pageYOffset & window.scrollTo & SessionStorage)

    业务场景 从列表跳转详情页,通过操作返回列表页时,滚动条仍然处于跳转前的高度,并加上 ease-out 的过渡动画. 由于sessionStorage是随页面即关即消的,所以比起VUEX.localS ...

  9. Object类、Date类、Calendar类、System类、StringBuilder类和基本类型包装类

    一.Object类--toString方法 1.普通类重写toString方法,不然打印出来是存在栈内存的对象引用名称的堆内存中该对象的地址值: 2.equals方法: String比较equals是 ...

  10. .Net性能调优-ArrayPool

    定义 高性能托管数组缓冲池,可重复使用,用租用空间的方式代替重新分配数组空间的行为 好处 可以在频繁创建和销毁数组的情况下提高性能,减少垃圾回收器的压力 使用 获取缓冲池实例:Create/Share ...