Greenplum 列存原理

Greenplum 在表的存储结构上分为 HEAP 表、AO 表。

其中 HEAP 表是 PG 数据库原生存储格式,也是 Greenplum 的默认存储格式,但是只支持行存储,并且不能压缩。AO 表为 append optimized 表,支持行存储、列存储,支持多种压缩算法与压缩级别。

AO 表原理

Greenplum 4.3 之前 AO 表为 appendonly 表,只能追加,即只能进行插入,不能更新和删除。Greenplum 4.3 之后,AO 表优化为 append optimized 表,支持插入、更新、删除。插入即在最后追加记录;删除通过维护一张 bitmap 表,标记被删除的行;更新则为删除和插入 2 个操作的组合。所以 append optimized 表在大量更新或删除之后,标记为无效的数据不会自动清除,需要使用 vaccum 命令回收这部分空间。

bitmap 表如下,通过 bit 位以及偏移量来判定 AO 表上的某一行是否被删除(其中 82342 为 AO 表的 relid,bitmap 表就为 pg_aoseg.pg_aovisimap_{relid}):

对于 heap 表,由 tupleid 决定每条记录的位置(tupleid 包含记录在文件中偏移位置),而对于 AO 表,数据是压缩的,没法确定 value 在文件中偏移位置,因此使用了 rownum,每条记录都有自己的 rownum,rownum 一直增长,每个 block 中记录了起始 rownum 以及 block 在文件中偏移位置,所以只要给定一个 rownum,就能定位到所在的 block,然后从 block 中就可以遍历到这个 rownum 对应的记录。

列存原理

列存只能是 AO 表,所以上一节中所有的 AO 表原理都适用。列存表,按列,每列对应一个或一批文件,每个列占用一个至多个文件,最多 128 个(预留 128 个 id),不同列的值不会同时出现一个文件。

列存表的文件存储,即(25854.1,25854.2 为第一列,25854.129、25854.130 为第二列,以此类推):

若只更新某1列或某几列,对于列存 AO 表,每个列文件之间并没有指针或其他关联,依靠相同的 rownum 来定位一行数据,所有列文件中该 rownum 数据全部作废,然后使用更新后的数据插入到新的一行中,此行中的所有 rownum 保留。因此,此时的数据更新,并不是只更新指定的列。所以单条 update 带来的 IO 开销很大,需要对每一个列文件都写入。

小结

对于 Greenplum 中的 AO 表,其实无论是行存或列存,更新所带来的性能降低是可以预估的。一条 SQL 语句的执行时间基本上可以简单的分为 IO 消耗的时间和计算时间。一张表在大量更新之后只会线性的增加 IO 时间,计算时间并不会受到影响。即假设表 A 通过 update 更新了 30% 的数据,同样的一条 SQL 执行时间的延长理论上不高于 30%。并且可以通过 vacuum 回收被删除数据的空间来恢复原有的查询性能。

发表评论

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

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据