选择表存储模型#

表的存储格式#

OushuDB 6.x 现在支持两种存储格式:MAGMA 和 HORC,两者都是列存格式。

第一种自研存储格式为 MAGMA,其底层采用开源的 ORC 格式的行列混合存储,有效地兼顾了分析型任务与交易型任务的需求。 就分析型任务而言,MAGMA 存储格式能够借助哈希分布、分片内并行等技术,并与新执行器相配合,从而达成高效的数据分析效果。 针对交易型任务,MAGMA 存储格式能够凭借索引实现高效的点查询等操作,并且具备严格的事务保障。

第二种自研存储格式称为 HORC,即 Hudi ORC 的缩写。它是基于 HDFS 存储的表格式,其数据文件同样主要以 ORC 格式呈现。 面向分析型任务时,通过哈希分布、分区裁剪、stripe 跳读等手段来加快数据查询的速度。

下面给出创建MAGMA和HORC表的几个例子。

-- 默认创建的 MAGMA 表 (可根据oushudb-tablespace.yaml修改默认设置)
CREATE TABLE magma_table1 (id int, rank int, year smallint,gender char(1), count int );

-- 显示写明tablespace
CREATE TABLE magma_table2 (id int, rank int, year smallint,gender char(1), count int ) TABLESPACE magma_default;

-- 显示写明tablespace以及一些with选项设置
CREATE TABLE magma_table3 (id int, rank int, year smallint,gender char(1), count int ) WITH (appendonly=true, orientation=magmaap) TABLESPACE magma_default;

-- 创建一个有primary key的 magmaap 表, MAGMA 内部自动实现了压缩。
CREATE TABLE magma_table4 (id int, rank int, year smallint,gender char(1), count int,primary key(id) ) TABLESPACE magma_default;
-- 创建 HORC 表
CREATE TABLE horc_table1 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly=true, orientation=horc) TABLESPACE dfs_default;

-- 创建一个snappy压缩的 HORC 表
CREATE TABLE horc_table2 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly=true, orientation=horc, compresstype=snappy) TABLESPACE dfs_default;

-- 创建一个不压缩的 HORC 表,如果不指定压缩类型的话,默认不压缩。
CREATE TABLE horc_table3 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly=true, orientation=horc) TABLESPACE dfs_default;

数据存储说明

特性

MAGMA

HORC

行/列存储

行列混存

行列混存

存储格式

自定义存储格式

自定义存储格式, 兼容标准ORC文件格式和Apache Hudi表格式

是否支持新执行器

支持

支持

压缩

支持LZ4, SNAPPY, ZSTD, ZLIB,用户可以不指定,由MAGMA表自动选择

支持LZ4, SNAPPY, ZSTD, ZLIB

是否UPDATE/DELTE

支持

支持

是否INDEX

支持

不支持

表的分布#

表的分布通常有哈希分布和随机分布。

哈希分布是指通过对分布键进行哈希运算,将具有相同哈希值的数据行分配到同一个存储节点上。 如果选择了合适的分布键,可以确保数据较为均匀地分布,进行某些查询时能快速定位需要查询的节点和摒弃不需要查询的节点,某些查询时能避免重新对表进行分布,从而提高查询性能。 哈希分布适用于数据分布相对固定、需要快速定位和访问数据的场景。

随机分布则是将数据行按照顺序依次发送到各个存储节点上,具有相同值的数据行不一定位于同一个存储节点上。 随机分布保证了数据绝对的平均分布,但在查询时需要所有节点,性能相对哈希分布可能会稍逊一筹。 然而,在某些情况下,例如数据分布本身就比较随机,或者难以确定合适的哈希分布键时,随机分布也可以是一种可行的选择。

在这个版本中,MAGMA表仅支持哈希分布,当然哈希分布也能发挥MAGMA最好的查询性能。HORC表支持哈希分布和随机分布。

创建MAGMA表是如果不指定分布键,MAGMA表会自动选定第一列作为分布键,并在NOTICE消息中指出选定的分布键。 哈希分片的bucket_num在magma-topology.yaml配置文件中配置的num_ranges分片数一致,无需用户手动指定。

-- 不指定分布键MAGMA表会自动选定第一列为分布键,以下两个建表语句等价
CREATE TABLE magma_tbl1 (id int, rank int, year smallint, gender char(1), count int) TABLESPACE magma_default;
CREATE TABLE magma_tbl2 (id int, rank int, year smallint, gender char(1), count int) TABLESPACE magma_default DISTRIBUTED BY(id);

-- 用户根据场景手动指定分布键(可以是多个)以取得更佳的查询效果
CREATE TABLE magma_tbl3 (id int, rank int, year smallint, gender char(1), count int) TABLESPACE magma_default DISTRIBUTED BY (rank, gender,year);

HORC表除了像MAGMA表那样支持哈希分布,还仍然能支持随机分布。 并且HORC表支持自己指定bucket_number,在建表语句中使用with选项指定。

-- 选用随机分布的HORC表
CREATE TABLE horc_tbl1 (id int, rank int, year smallint,gender char(1), count int) TABLESPACE dfs_default DISTRIBUTED RANDOMLY;
-- 可以手动指定bucket_number(注意,MAGMA表不可以手动指定)
CREATE TABLE horc_tbl2 (id int, rank int, year smallint,gender char(1), count int) WITH (bucket_number = 10) TABLESPACE dfs_default DISTRIBUTED BY (id);

体现哈希分布的简单例子#

Random 分布的表较灵活,在系统扩容添加节点后无需重新分布数据。而 Hash 分布的表在系统扩容后,为 了利用新增加节点的计算能力,需要重新分布数据。另外,针对 Hash 分布的表资源管理器在分配资源的 时候采取分配固定 virtual segment 数的方式,不如 Random 分布灵活。

Hash分布的表在某些查询上会有性能上的好处,因为有时可以避免重新分布某些表。

例如下面例子的查询,如果 lineitem 和 orders 两张表分别按照 l_orderkey 和 o_orderkey 分布,则这个查 询在执行时不再需要重新分布任何一张表就可以并行在各个节点并行执行连接操作。

SELECT l_orderkey, count(l_quantity)
FROM lineitem, orders
WHERE l_orderkey = o_orderkey

针对绝大多数查询,实验表明都不是网络瓶颈,基于 Hash 分布和基于 Random 分布性能差别不大。所以我 们建议用户默认采取 Random 分布, 只针对特定需要优化的场合使用 Hash 分布的表。

MAGMA表同时具备哈希分布和随机分布的优势,通过 VC 属性值 magma_hash_table_nvseg_perseg 来控制每个节点能启动的virtual segment数。 在系统扩容后不需要重新分布数据。

Hash 分布的表 bucket_number 的选取#

针对 Hash 分布的表,bucketnum 决定了一个查询的并行度。在一些常见的硬件配置中(128G内存和12块SAS盘),我们建议选取6 * 节点数或者8 * 节点数。 硬件更好的话可以增加 bucket_number。在系统初始化 的时候,default_hash_table_bucket_number 的初始化默认值为8 * 节点数。

备注

只有HORC表支持建表时各自指定bucket_number,MAGMA表整个VSC中所有表的bucket_number就是magma-topology.yaml中指定的num_ranges分片数。

也就是说HORC表每张独立的表都可以各自指定bucket_number,而MAGMA表同一个VSC中所有表都共享一个bucket_number。

Hash 分布键的选取#

在选择分布键的时候, 我们要考虑用户的应用场景。当进行两表连接的时候,如果连接条件发生在分布键上,那么相同的数据就在同一个数据节点,数据不需要重新进行分布。对于大数据量的表,要参考用户的查询来优化分布键。 同时,分布式系统希望数据均匀地分布在各个节点, 这样各个节点均匀地使用资源,避免出现单个节点处理很慢的场景。所以我们还要根据数据特点来选择,使得数据均匀分布。

下面的语句可以查看一个表的数据分布

SELECT gp_segment_id, count(*) as cnt FROM tbl GROUP BY gp_segment_id;

其中gp_segment_id是对于segment 的唯一标识,这样列出了rank 表在每个segment上的数据个数, 从而看到数据是否均匀分布。