合并的耗时与参与合并的分区数以及需要扫描、合并的宏块数直接相关。在 OceanBase V4.x 版本,以下两种典型的场景下可能需要进行合并的调优:
- 百万分区场景:益于架构优化,OceanBase V4.x 版本的一个 OBServer 或一个租户可以支持高达百万分区,更多的分区意味着更长的合并耗时。
- 列存场景:在使用列式存储存(V4.3),因为增量数据全部是行存形式,而基线数据是列式存储,所以在对增量数据与老基线数据进行合并时,需要将行存的增量数据拆分到每个列的独立 SSTable 中,这会导致合并时间和资源占用相较于行存有较大的增加。
架构变化对合并的影响
OceanBase V4.x 版本为了支持超大数量的分区,对 SSTable 的结构进行了重构,SSTable 中宏块的 Meta 信息落盘保存,并按需加载到内存中。而在以前的版本中,这些 Meta 信息不落盘,始终保存在内存中,合并时也无需写 Meta 信息。
这个变化会对合并的性能产生一定的影响,特别是在大量分区的场景下,OceanBase V4.x 版本的合并速度会比之前的版本慢一些。举一个极端的例子,在 OceanBase V4.x 版本为一个租户创建 60W 个空分区,使用默认参数的情况下,租户合并耗时 2 个小时。
列式存储对合并的影响
列存表的数据合并行为与行存数据有显著差异。因为增量数据全部是行存形式,所以在与基线数据合并后,需要再次拆分到每个列的独立 SSTable 中,这会导致合并时间和资源占用相较于行存有较大的增加。当然,为了应对这一挑战,OceanBase 数据库对列存表的合并进行了大幅优化,不仅支持水平拆分并行合并加速,还新增了垂直拆分加速机制,允许将多个列的合并操作置于同一任务中进行,列数可依据系统资源动态调整,确保合并过程既高效又经济。
在列存表模式下,由于数据按列存储,更为集中,每个宏块包含的行数非常多。如果用户使用随机更新的模式对表执行大量的 DML,如果使用的是列存表,合并时需要处理的宏块/微块数会比使用行存表时更多,这也是在使用列存时合并速度较慢的一个典型场景。
合并加速
OceanBase V4.x 版本以租户为粒度执行每日合并,可以根据不同租户的具体场景和要求,设置不同的合并参数。通常,可以调节合并任务的并发线程数来调节合并的速度,而对于分区数特别多的场景,还需要调节与合并调度相关的参数。
以百万分区场景为例,建议的相关参数设置如下:
compaction_dag_cnt_limit:用于配置 Compaction DAG 队列上 DAG 数量的上限值。默认值为 15000,建议调整为 50000。compaction_schedule_tablet_batch_cnt:用于配置 Compaction 分批调度时,每个批次调度的分区数的上限值。默认值为 50000,建议调整为 100000。compaction_low_thread_score:合并任务的并行线程数。默认值为 0,实际代表 6 个线程,建议调整为 20。compaction_high_thread_score:转储任务的并行线程数。默认值为 0,实际代表 6 个线程,建议调整为 20。
alter system set compaction_schedule_tablet_batch_cnt = 100000;
alter system set compaction_dag_cnt_limit = 50000;
alter system set compaction_low_thread_score = 20;
alter system set compaction_high_thread_score = 20;
适用版本
OceanBase 数据库 V4.x 版本。