当前位置:   article > 正文

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

数仓实践丨从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。

cke_121.png

​ 图1 列存储

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

2.3 HStore

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

cke_122.png

​ 图2 HStore存储

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

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

数仓类型

列存的delta表

HStore的delta表

表结构

与列存主表的表定义一致

与主表表定义不一样。

功能

用于暂存小批量insert的数据,满阈值后再merge到主表,避免直接insert到主表产生大量小CU。

用于持久化存储update/delete/insert等操作信息。

缺陷

来不及merge导致delta表膨胀,影响查询性能,同时无法解决并发update的锁冲突问题

依赖后台常驻autovacuum来做merge操作。

利用特有的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。

cke_123.png

图3 CU管理

3.3 解决思路

3.3.1 小CU合并

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

cke_124.png

图4 小CU合并

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

cke_125.png

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

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

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

3.3.2 0CU清理
  1. 0CU的处理比小CU的处理简单的多,我们直接从CUDESC表中将0CU记录删除即可。这里指的删除天然支持MVCC,因此老的快照查询依然可以访问被删除的记录。
  2. 小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的聚簇性无法达到要求:

  1. 写入数据时,如果不是批量导入,则不会把数据写入排序器,而是直接插入delta表,当delta表merge的时候,也不会先走排序逻辑,而是直接将数据写入CU;
  2. 当CU中的数据被删除的足够多时,就变成了小CU,聚簇性本身就会变差,就算进行了小CU合并,也依然不会走排序逻辑,而是将数据直接写入delta表,merge流程与1)一致;
  3. 实际上就是增加数据+删除数据。

4.2 解决思路

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

cke_126.jpeg

图6 异步排序基本原理

4.3 效果

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

5. 总结

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

  1. 大致介绍了GaussDB实时数仓的重要解决方案:HStore;
  2. 引出小CU问题并给出了解决方案;
  3. 从数据的聚簇性作为切入点,提出异步排序来优化HStore表的scan性能;

6. 参考文档

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/165715
推荐阅读
相关标签
  

闽ICP备14008679号