破解OceanBase存储引擎读放大难题的方法

破解OceanBase存储引擎读放大难题的办法

首先给大家推荐一下OceanBase开源负责人老纪的公众号“老纪的技术唠嗑局”,这里会持续更新和#数据库、#AI#技术架构相关的各类技术内容。感兴趣的朋友可以关注哦!

前言

OceanBase的LSM-Tree存储引擎本身有着高效的写入性能,它既能通过旁路导入来高效处理定期的批量数据同步,还能承接一些实时数据同步以及历史库数据修改的场景。

但任何事物都有两面性,LSM-Tree存储引擎虽然对写操作比较友好,可在数据读取的时候,必然会绕不开多级数据归并带来的读放大问题。

最近一段时间,在社区论坛和微信群里经常出现这样的情况:在高频插入、删除和更新的表中,读取性能没有达到预期。这篇文章就简单跟大家介绍一下应对的办法。

背景:OceanBase的存储引擎架构

OceanBase的存储引擎是基于LSM-Tree架构的,它把数据分成基线数据(放在基线SSTable里)和增量数据(放在MemTable/转储的SSTable里)两部分。其中基线数据是只读的,一旦生成就不会再被修改;增量数据支持读写。

OceanBase数据库的DML操作,像插入、更新、删除等操作,首先会写入内存里的MemTable,所以在写入性能上就类似于内存数据库的写入性能。当MemTable达到一定大小的时候就会转储到磁盘成为增量的SSTable(就是上图中的转储SSTable部分),转储到磁盘上的过程是批量的顺序写,和B+树架构离散的随机写相比,会大大提高写盘的性能。

当增量的SSTable达到一定规模的时候,就会触发增量数据和基线数据的合并,把增量数据和基线数据做一次整合,基线数据在合并完成之后就不会再变化了,直到下一次合并。而且每天凌晨业务低峰期的时候,系统也会自动进行每日合并。

不过LSM-Tree的架构也存在一个问题,就是读放大(上图中右侧箭头向上的部分)。在进行查询的时候,需要分别对SSTable和MemTable进行查询,然后把查询结果归并一次,再把归并后的查询结果返回给SQL层。OceanBase为了减小读放大带来的影响,在内存里实现了多级缓存,比如Block Cache和Row cache,来避免频繁对基线数据进行随机读。

问题:Buffer表效应

当用户在某张表上频繁执行插入并且同时进行批量删除,或者有大量的并发更新操作时,可能会出现这样一种现象:表中的数据行数并不大,但是查询和更新的性能明显下降。这种现象在OceanBase中被称为Queuing表(业务上有时候也叫Buffer表)效应。

Buffer表是LSM-Tree架构数据库都得面对的一类问题。在LSM-Tree架构下,删除操作在合并之前都只是逻辑上标记删除,并不是物理删除,当增量数据里存在大量标记删除的数据时,物理行数量会远多于逻辑行数,从而会严重加剧存储引擎的读放大现象,还会影响优化器对最优计划的选择。

分析:通过explain extended_noaddr

分析方法很简单,用EXPLAIN EXTENDED_NOADDR命令对SQL进行详细的计划展示就行(通常用户排查SQL性能问题的时候,会用这种展示模式)。需要重点关注physical_range_rows和logical_range_rows的值。

上图中,physical_range_rows和logical_range_rows分别表示t1表需要扫描的物理行数和逻辑行数。要是走了索引的话,意思就是t1表在索引上需要扫描的物理行数和逻辑行数。

一般情况下,physical_range_rows和logical_range_rows这两个指标是差不多的,看任意一个都行。只有在这个特殊的Buffer表(频繁更新)场景下,physical_range_rows可能会远大于logical_range_rows,所以可以通过physical_range_rows和logical_range_rows的数值来判断是不是出现了Buffer表问题。

比如说我向t1表插入33行数据,马上删除29行,那在增量数据里就会有33个物理行,其中29个物理行有Delete标记,查询真正的4个逻辑行的时候,就会出现大量无效扫描动作。

应对:Buffer表自适应合并优化

为了更灵活地解决Buffer带来的性能下降问题,从OceanBase 4.2.3开始,为大家带来了Buffer表自适应合并优化特性

这个特性允许用户根据业务场景给每张表设置不同的表级配置项table_mode来指定不同的快速冻结与自适应合并策略,以此应对Buffer表引起的读放大现象,从而提高系统长期运行下的QPS等性能指标。

针对Buffer表问题,OceanBase提供了5种档位的Table Mode支持。不同的Table Mode对应不同的统计信息阈值与合并策略。存储层每次转储的时候都会根据转储的统计信息以及Table Mode对应的阈值来判断是否需要执行一次针对Buffer表场景的特殊合并,把增量数据里的所有Delete标记消除掉,避免原有的大量无效扫描动作。

Table Mode 转储后触发合并阈值 转储后触发合并概率 转储后合并类型
Normal(默认值) 较高(为基准1.0 ) 极低 仅做Medium Compaction
Queuing 高(0.9)
Moderate 中(0.8) 优先做Medium Compaction, 若Medium冷却中,做Meta
Super 低(0.6)
Extreme 极低(0.5) 较高 仅做Meta Compaction

备注:

合并是OceanBase数据库将动静态数据做归并的行为,能有效消除增量数据

  • Medium Compaction是一类触发链路较长,需要保证多副本上Major一致性的合并,合并较慢
  • Meta Compaction是由各个Observer主动发起,生成只读Meta SSTable的合并,合并较快

简单来说,默认场景(Normal)下转储后发起合并的门槛比较高(比如觉得转储中删除行超过30万才判断可能是Buffer表场景),所以转储后触发合并概率比较低,触发的也是合并速度较慢的Medium Compaction。

而随着Table Mode逐步上调,转储后发起合并的门槛逐渐降低,触发合并的概率也逐渐提高,并且更倾向于做合并速度较快的Meta Compaction,从而能及时通过合并消除增量数据,避免Buffer表带来的大量无效扫描。

具体来说,不同参数下的策略可以分为如下三个模块:

触发快速冻结

对创建时间>存活时间阈值,且memtable有热点行(不在本次优化考虑内)或墓碑现象的触发快速冻结:

Table Mode 存活时间阈值 墓碑现象阈值
Normal(默认) 120s = 120s * 1.0 (更新行 + 删除行)> 25w = 25w * 1.0
Queuing 108s = 120s * 0.9 (更新行 + 删除行)> 22.5w = 25w * 0.9
Moderate 96s = 120s * 0.8 (更新行 + 删除行)> 20w = 25w * 0.8
Super 72s = 120s * 0.6 (更新行 + 删除行)> 15w = 25w * 0.6
Extreme 60s = 120s * 0.5 (更新行 + 删除行)> 12.5w = 25w * 0.5

备注:

存活时间阈值的120s为4.2的阈值。在4.3及以上版本,此阈值为300s。

转储时收集统计信息并尝试触发分区合并

冻结后紧接着会做一次转储,若转储同时满足如下条件,将会进行tablet级别的信息汇报:

  • dml数量 > 1000
  • insert + update + delete行数 > 1000

当然,tablet信息的汇报并不止于转储,一些慢查询场景也会做相应处理,只是不在本任务范围内。

当memtable超过预设内存阈值或快速冻结触发后都会执行一次转储。如果触发了快速冻结,意味着墓碑现象可能已经出现了,因此根据上述快速冻结策略的墓碑策略再判断一次,如果命中,直接发起一次合并。

分区合并调度时调度分区合并

分区合并的调度由一个独立的调度线程负责,基本逻辑是通过自适应合并的策略来判断某个tablet是否需要执行一次分区合并。相应地,也会根据不同的table mode调整自适应策略。

与table mode有关的自适应合并策略如下:

备注:

这里引用一下OB官网的 自适应合并 内容:

其中第三点:根据统计增量数据的总行数这个并不受table mode控制,增量行数的阈值是超过10w或者增量行达到极限70%,对于非Normal表,大概率已经触发合并了。

导数场景

Table Mode 导数场景条件(需同时满足)
根据统计的10分钟内信息
热点tablet
且操作行数满足 (操作行数 = insert + delete + update)
Normal(默认) 查询次数 + 转储次数 > 5 = 5 * 1.0
Queuing 查询次数 + 转储次数 > 4.5 = 5 * 0.9
Moderate 查询次数 + 转储次数 > 4 = 5 * 0.8
Super 查询次数 + 转储次数 > 3 = 5 * 0.6
Extreme 查询次数 + 转储次数 > 2.5 = 5 * 0.5

墓碑场景

Table Mode 墓碑场景条件(需同时满足)
当转储次数 ≥ 2
且根据统计的10分钟内信息 操作行数 = insert + delete + update
Normal(默认) 操作行数 > 1w = 1w * 1.0
Queuing 操作行数 > 9k = 1w * 0.9
Moderate 操作行数 > 8k= 1w * 0.8
Super 操作行数 > 6k = 1w * 0.6
Extreme 操作行数 > 5k = 1w * 0.5

与此同时,为了防止10分钟内的信息不够全面,统计了tablet自上次medium/meta时的删除行总数,并有满足如下条件时触发一次合并。

Table Mode 总删除行数
Normal(默认) 总删除行 > 30w
Queuing 总删除行 > 20w
Moderate 总删除行 > 10w
Super 总删除行 > 5w
Extreme 总删除行 > 1k

但是值得一提的是, 总删除行这个条件属于锦上添花类型,类似于cache,很有可能未满足条件时tablet统计信息就被别的tablet刷掉了。同时,按照最宽松的10分钟内1w的条件,如果每个10分钟内信息都是9999行,要达到30w的阈值也得近300分钟,作用是更多是在tablet数量少的时候留下来兜底。

低效读场景

Table Mode 低效读场景条件(需同时满足)
根据统计的10分钟内信息
热点tablet
Normal(默认) 查询次数 + 转储次数 > 5 = 5 * 1.0
Queuing 查询次数 + 转储次数 > 4.5 = 5 * 0.9
Moderate 查询次数 + 转储次数 > 4 = 5 * 0.8
Super 查询次数 + 转储次数 > 3 = 5 * 0.6
Extreme 查询次数 + 转储次数 > 2.5 = 5 * 0.5

使用指南

创建表时指定Table Mode

用户可以在创建表的时候就显式指定Table Mode,要是不指定的话默认就是Normal模式。

# 语法
create table t1 (c1 int) table_mode = 'normal/queuing/moderate/super/extreme';

# 创建一张queuing模式的表
create table t1 (k int, v double) table_mode = 'queuing';

# 创建一张extreme模式的表
create table t1 (k int, v double) table_mode = 'extreme';

修改表的Table Mode

用户可以通过DDL语句显式修改Table Mode

# 语法
alter table t1 set table_mode = 'normal/queuing/Moderate/Super/Extreme';

# 修改表的table_mode为moderate
alter table t1 set table_mode = 'moderate';

比如说,当用户观测到某张表的读放大现象严重,出现Buffer表现象的时候,可以根据业务量规模与特点手动把该表的Table Mode调到更高档位,比如从normal调整到queuing,从queuing调整到super等。当Table Mode在存储层生效后,将会通过调度自适应合并的方式发起合并来解决Buffer表现象。

与此同时,更激进的Table Mode会更频繁地发起合并,从而消耗更多的计算资源,如果此时业务体量或场景能够容忍一定程度的Buffer表效应,也可以手动调低数据表的Table Mode。

Table Mode生效说明

值得说明的是,尽管Table Mode在Table Schema中是实时生效的,但是在存储层后台对tablet信息的统计是延迟更新的(2分钟刷新一次),所以当修改表的Table Mode后,平均得经过60s才能生效。

另外,存储层后台对每个租户下转储统计信息的覆盖范围是有限的,由于资源有限,并不是所有tablet上的转储信息都会被统计到,只有转储时满足某些特定条件的tablet

文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/12917.html

(0)
LomuLomu
上一篇 5小时前
下一篇 3小时前

相关推荐

  • 履约系统:应用层、领域层、集成关系设计

    大家好,我是汤师爷~ 在这篇文章中,我们一起探讨订单履约系统的应用架构设计。 应用架构设计 我们前面讨论了系统的核心概念模型和拆单逻辑。接下来,让我们从应用架构的角度,深入了解系统的各个层次。这包括应用层、领域层,以及与其他系统的集成关系。 应用层能力 应用层定义软件的应用功能,它负责接收用户请求,协调领域层能力来执行任务,并将结果返回给用户,核心模块包括:…

    2025 年 1 月 1 日
    25100
  • Java 技术新纪元 —— 基于 Java 的联邦学习技术推动跨行业数据协同创新(238)

    🌟亲爱的技术爱好者们,诚挚欢迎访问【青云交的技术天地】!在这个数字化浪潮席卷全球的时代,我们相聚于此共同探索前沿科技。这里不仅是知识分享的平台,更是思想碰撞的舞台,期待与您携手共创技术新篇章!🌟全网平台(微信公众号/CSDN/抖音/华为/支付宝/微博):青云交一、加入【技术精英社群】快速加入通道1:【青云交技术精英圈】快速加入通道2:【CSDN 技术创作交流…

    2025 年 5 月 12 日
    9200
  • 2024 IDEA最新激活码,IDEA永久免费激活码2025-01-15 更新

    IDEA 2024最新激活码 以下是最新的IDEA激活码,更新时间:2025-01-15 🔑 激活码使用说明 1️⃣ 复制下方激活码 2️⃣ 打开 IDEA 软件 3️⃣ 在菜单栏中选择 Help -> Register 4️⃣ 选择 Activation Code 5️⃣ 粘贴激活码,点击 Activate ⚠️ 必看!必看! 🔥 获取最新激活码: 实时更…

    2025 年 1 月 15 日
    65900
  • 架构师启示录:知识模型、落地方法与思维模式PDF、EPUB免费下载

    适读人群 :资深程序员、初级架构师 从架构知识模型、架构落地方法、架构思维模式三大维度介绍架构师的能力模型,带你穿越“认知迷雾” 电子版仅供预览,下载后24小时内务必删除,支持正版,喜欢的请购买正版书籍 点击原文去下载 书籍信息 作者: 灵犀出版社: 机械工业出版社出版年: 2024-3页数: 212装帧: 平装丛书: 架构师书库ISBN: 97871117…

    2025 年 1 月 11 日
    35700
  • 2025年最新DataGrip激活码永久破解教程(支持2099年)

    本教程适用于JetBrains全家桶(包括IDEA、PyCharm、DataGrip、Golang等),手把手教你永久激活至2099年! 先看破解成功效果图,有效期已成功延长至2099年: 下面将详细介绍DataGrip的完整激活流程,该方法同样适用于历史版本,无论你使用什么操作系统都能完美适配! 下载DataGrip安装包 若已安装可跳过此步骤 访问Jet…

    2025 年 5 月 8 日
    15500

发表回复

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

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信