写点什么

数仓实践丨从 CU 入手优化 HStore 表

  • 2024-02-27
    广东
  • 本文字数:3180 字

    阅读完需:约 10 分钟

数仓实践丨从CU入手优化HStore表

本文分享自华为云社区《GaussDB(DWS)存储引擎:从CU入手优化HStore表》,作者: yd_261437590。

1. 前言


  • 适用版本:【8.2.1(及以上)】


HStore 同时拥有处理传统 TP 场景的事务能力和强大的数据分析能力,但是强大的数据分析能力很可能被小 CU 问题给破坏,另外,将多个 CU 排序可以增加 HStore 的数据聚簇性,因此作者通过解决小 CU 问题和提升数据聚簇性两种方式对 HStore 表的存取能力进行优化。

2. HStore 简介

2.1 行存储


传统 OLTP(OnLine Transaction Processsing 联机事务处理)场景与功能、业务强相关,数据需要进行频繁的增删改查,这时比较适合使用行存储式。行存储的优势主要有两个方面:首先是点查性能好,在点查场景下可以直接索引到某行数据的元组位置;其次就是更新效率高,行存储在实时并发入库,并发更新方面依然有着比较大的优势。

2.2 列存储


传统行存储形式的数据库主要为业务服务,但是如果涉及到分析查询场景,特别是在数据量大且复杂的查询时,就会遇到性能瓶颈了,性能瓶颈是数据存储方式决定的。因此 OLTP(OnLine Transaction Processsing 联机事务处理)场景一般会交给列存储引擎去做。列存储的优势主要有两方面:首先是批量查询性能好,当分析查询只涉及某列或者某几列,不需要访问无关列,特别是在表的宽度比较大时(如一千列),优势更加明显;其次就是列存储的压缩性能更高,原因就是因为数据按列存储,单列类型相同。


列存储引擎的最小存储单位是 CU(Compression Unit, 压缩单元):一个 CU 是由表中某一列的一部分数据组成的压缩数据块, 通过(cu_id,col_id)标识一个 CU。


图 1 列存储


另外,列存引擎通过 delta 表,避免了小 CU 的产生,显著提升列存表单条导入的性能,同时解决由于小 CU 导致的数据膨胀问题。当单条或小批量数据导入到列存表时,需先存入 delta 表,当 delta 表中数据积攒到指定行数时再存入新产生的 CU 中。

2.3 HStore


列存储优势明显,但是劣势也比较明显,传统列存表基本无法支持并发更新入库。随着业务复杂程度的提升,出现了对于实时入库和实时查询有较强诉求的场景,这要求数据库同时拥有处理传统 TP 场景的事务能力和强大的数据分析能力。这时就可以使用 HStore 来处理这些场景了。


图 2 HStore 存储


HStore 利用 delta 表存储 update/delete/insert 等操作信息。之后依赖后台常驻 autovacuum 来做 merge 操作将数据写入主表。


HStore 的 Delta 表与普通列存 Delta 表的对比



利用特有的 delta 表,HStore 解决了传统列存表 CU 锁的问题,支持上游 upsert/update 等操作实时并发入库。同时还能保证和普通列存表相近的数据分析与数据压缩能力。


HStore 表技术特点如下:


  • 完整的事务一致性:支持全面的事务能力,数据插入或者更新提交后即可见不存在时延,保证数据 ACID 一致性。

  • 全面的功能支持:提供和当前列存一样全面的功能和语法支持。

  • 查询性能好:适用多表关联等复杂 AP 查询场景,相对于传统行存表,拥有更完善的分布式查询计划与更先进的分布式执行器,性能优势明显。支持复杂的子查询和存储过程,支持主键等传统索引能力去重和加速点查,也支持分区、全局字典、局部排序等方式进一步加速 AP 查询。

  • 入库快:彻底解决列存 CU 锁冲突问题,支持高并发的更新入库操作,典型场景下,并发更新性能是之前的百倍以上。

  • 高压缩:数据在 MERGE 进入列存主表后,按列存储具有天然的压缩优势,能极大地节省磁盘空间与 IO 资源。

3. 小 CU 问题

3.1 问题诱因


  1. 有些实时表入库量并不大,不定期会有入库,因为 merge 的判断标准有两个:行数或者时间,超过时间没有入库后也会强制 merge,这种情况下 merge 产生的 CU 的行数不可控,可能产生小 CU;

  2. 对于缓慢变化维表来说,可能很长时间才改变一次,每次都可能产生一个小 CU,虽然不会有太多这种小 CU,但长期运行后,这种维度表数量还很多的情况下,小 CU 的数量就会到达影响系统性能的级别;

  3. 频繁 upsert、update、delete 等更新后,CU 中大部分数据被标记删除,这样的 CU 虽然会被列存 vacuum 通过填充 NULL 进行回收,但是依然会导致小 IO 和 cudesc 表的膨胀,进而影响性能。

3.2 问题影响


  1. CUDesc 并不会因为 CU 变小而变小,因此当小 CU 过多会导致存储利用率过低。比如一个 1000 列的大宽表产生的 CU 只包含 1 行数据,但是因为每一列都会在 CUDESC 表中记录,CUDesc 也会增加一千多行数据;

  2. 只剩下几十行甚至几行的小 CU 会引发大量的小 IO;

  3. 粗过滤效率降低,因为 CUDESC 表中会存储 CU 的最值,当进行查询时可以先通过最值进行粗过滤,但是如果 CU 中数据太少导致数据范围小,则会降低粗过滤效率;

  4. 降低压缩率。因为数据压缩是以 CU 为单位的,但是 CU 过小会导致压缩表现达不到预期

可以认为 0 CU 其实是小 CU 的一种特殊极端情况,0 CU 相对非 0 的小 CU 对于性能影响小很多,因为 0 CU 只用加载 deletemap。


图 3 CU 管理

3.3 解决思路

3.3.1 小 CU 合并


小 CU 合并不是直接产生新的 CU,而是将小 CU 数据重新插入到 delta 表后标记删除,然后依赖 delta 表的自动 merge 攒够后再产生完整的新 CU;


图 4 小 CU 合并


和正常的 delta merge 不同在于,小 CU 被标记删除后新插入 delta 表的记录会申请新的 ctid,因为 ctid 是变化的,所以该操作和 DML 操作存在冲突。当 DML 操作时遇到小 CU 合并,使用等待重试的方式处理;当 compact 操作时遇到 DML 冲突时直接跳过即可,原因就是删除和更新操作还是会将数据标记删除,因此可以直接放弃合并此条数据。


图 5 小 CU 合并时单条数据的处理


小 CU 合并的事务可见性基于现有的 csn 机制,compaction inprogress 或者回滚对外不可见,还是看到老记录,compaction 提交老记录就不再可见看到新记录。


具体一个 CU 中剩余多少条数据才算是小 CU,应该是与业务强相关。因此,小 CU 阈值应该可以使用 GUC 参数调节

3.3.2 0CU 清理


0CU 的处理比小 CU 的处理简单的多,我们直接从 CUDESC 表中将 0CU 记录删除即可。这里指的删除天然支持 MVCC,因此老的快照查询依然可以访问被删除的记录。


小 CU 合并的过程就是不断的尝试把小于一定阈值的 CU 标记删除,转移数据到 delta 中,直到这个 CU 全部被标记删除后变成 0 CU,就可以当做 0 CU 彻底清理。

3.3.3 效果


成功解决小 CU 问题,并且在小 CU 合并期间对实时入库性能几乎没有影响(推荐小 CU 行数阈值下 upsert 性能劣化 1%),但是因为小 CU 问题的解决,可以很好的解决查询性能劣化,空间膨胀等问题,并且小 CU 合并完成后,最终实时入库性能还是会有显著提升。

4. 提升数据聚簇性

4.1 需求来源


在对 HStore 进行点查时,会首先通过 CU 的 min/max 来进行粗过滤,我们希望通过 min/max 过滤掉大部分数据,这就要求每个 CU 的数据尽可能的接近,而不能过于分散。目前 GaussDB 已经实现了局部聚簇 (Partial Cluster Key, 简称 PCK),在数据批插过程中就会进行排序。但还是会有如下几种情况导致 CU 的聚簇性无法达到要求:


  • 写入数据时,如果不是批量导入,则不会把数据写入排序器,而是直接插入 delta 表,当 delta 表 merge 的时候,也不会先走排序逻辑,而是直接将数据写入 CU;

  • 当 CU 中的数据被删除的足够多时,就变成了小 CU,聚簇性本身就会变差,就算进行了小 CU 合并,也依然不会走排序逻辑,而是将数据直接写入 delta 表,merge 流程与 1)一致;

  • 实际上就是增加数据+删除数据。

4.2 解决思路


通过将 HStore 中多个 CU 的数据根据 partial cluster key 进行排序,生成新的 CU 再重新写入,新 CU 的数据会有更高的聚集性,即 CU 的 min,max 会在一个较小的区间内。异步排序时的并发处理与小 CU 合并类似,见 3.3.1。


图 6 异步排序基本原理

4.3 效果


经过测试,排序后的 CU 聚簇性极大提升,粗过滤效率的提升与原本的数据特征有关。但是排序过程中会对所有参与排序的 CU 加 CU 级锁,此过程会阻塞部分 DML 操作,因此不建议在业务高峰期使用此功能。

5. 总结


本文主要讲解了如下几个方面:


  1. 大致介绍了 GaussDB 实时数仓的重要解决方案:HStore;

  2. 引出小 CU 问题并给出了解决方案;

  3. 从数据的聚簇性作为切入点,提出异步排序来优化 HStore 表的 scan 性能;

6. 参考文档


数仓实时入库利器:HStore 表原理与应用实践详解。 作者:马俊松(华为云 GaussDB(DWS) 技术布道师)


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 4
用户头像

提供全面深入的云计算技术干货 2020-07-14 加入

生于云,长于云,让开发者成为决定性力量

评论

发布
暂无评论
数仓实践丨从CU入手优化HStore表_数据库_华为云开发者联盟_InfoQ写作社区