选择表存储模型

表的存储格式

OushuDB现在支持多种存储格式:AO,Parquet,ORC,MagmaAP。AO是按行存储的格式,而Parquet,ORC,MagmaAP是按行列存储的格式。 其中MagmaAP 是在4.0.0.0发布的全新的存储格式。MagmaAP,ORC都支持update/delete, 且MagmaAP还支持index。

下面给出创建AO, Parquet, ORC 和MamaAP表的几个例子。

# 默认创建的是AO表
CREATE TABLE rank1 (id int, rank int, year smallint,gender char(1), count int );

# 和上面的创建的表一样,显式指定存储格式类型
CREATE TABLE rank2 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly =true, orientation =row);

# 创建一个snappy压缩的AO表
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly =true, orientation =row, compresstype = snappy);

# 创建一个snappy压缩的Parquet表,如果不指定压缩类型的话,默认不压缩。
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly =true, orientation =parquet, compresstype = snappy);

# 创建一个不压缩的ORC表,如果不指定压缩类型的话,默认不压缩。
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly =true, orientation =orc);

# 创建一个带压缩的ORC表,需指定压缩类型。
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly =true, orientation =orc, compresstype = lz4);

# 创建一个压缩的magma表, magma 内部自动实现了压缩。
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int ) format 'magmaap';

# 创建一个有primary key的magma表, magma 内部自动实现了压缩。
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int,primary key(id) ) format 'magmaap';

数据存储说明

特性 AO PARQUET ORC MAGMA
行/列存储 行列混合存储 行列混合存储 行列混合存储
特性 AO PARQUET ORC MAGMA
存储格式 自定义存储格式 兼容Parquet1.0格式 兼容标准ORC 格式 自定义存储格式
是否支持新执行器 不支持 不支持 支持 支持
压缩 支持SNAPPY, ZLIB 支持SNAPPY,GZIP 支持SNAPPY, LZ4 自动选择压缩算法, 不需要用户指定
是否UPDATE/DELTE 不支持 不支持 支持 支持
是否INDEX 不支持 不支持 不支持 支持

表的分布

在OushuDB中,表可以两种方式分布方式:基于Hash的分布和Random分布。基于Hash的分布方法基于分布列的Hash值进行分布,Random分布采取随机分布模式。MagmaAP 兼具了Hash 分布和Random 分布的优点,不再显示地支持Rndom 分布。其他格式支持两种分布格式。

创建表时用户不指定分布方式的时候非MagmaAP表默认使用Random分布。下面这个两个例子等价。

CREATE TABLE rank (id int, rank int, year smallint,gender char(1), count int );

CREATE TABLE rank (id int, rank int, year smallint,gender char(1), count int )
DISTRIBUTED RANDOMLY;

下面这个例子创建一个Hash分布的表,分布的Key使用三个列(rank, gender, year)的组合,数据分布到32个bucket里面。

如果不指定bucketnum的话,系统默认使用default_hash_table_bucket_number系统参数的值来做为bucketnum。

CREATE TABLE rank (id int, rank int, year smallint,gender char(1), count int )
WITH (bucketnum = 32)
DISTRIBUTED BY (rank, gender,year);

注意:MagmaAP 使用系统参数 default_magma_hash_table_nvseg_per_seg 来决定每个节点上的bucketnum, 所以不需要也不支持在>创建表的时候指定bucketnum。

创建MagmaAP表时用户不指定分布方式的时候默认使用Hash 分布,默认分布列为第一列。下面这个两个例子等价。

CREATE TABLE rank (id int, rank int, year smallint,gender char(1), count int ) FORMAT 'MAGMAAP';

CREATE TABLE rank (id int, rank int, year smallint,gender char(1), count int )
FORMAT 'MAGMAAP' DISTRIBUTED by (id);

Hash分布和Random分布的选取

非Magma表: 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表具备的Hash和random 表的优势,通过 default_magma_hash_table_nvseg_per_node 来控制每个节点能启动的virtual segment数。 在系统扩容后不需要重新分布数据。

Hash分布的表bucketnum的选取

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

Hash分布键的选取

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

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

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

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