选择表存储模型
本页目录
选择表存储模型#
表的存储格式#
OushuDB现在支持多种存储格式:ROW,ORC,Hudi,MagmaAP。ROW 是按行存储的格式,而 ORC,Hudi,MagmaAP 是按行列存储的格式。
下面给出创建ROW, ORC 和MamaAP表的几个例子。
# 默认创建的是 ORC 表
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压缩的 ROW 表
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly =true, orientation =row, 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);
# 创建一个普通的Hudi表,相比ROW/ORC表,需要指定type,默认不压缩。
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly =true, orientation =horc, type = mor);
# 创建一个带压缩的Hudi表,需指定压缩类型。
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int ) with (appendonly =true, orientation =horc, type = mor, compresstype = lz4);
# 创建一个压缩的 magmaap 表, magma 内部自动实现了压缩。
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int ) format 'magmaap';
# 创建一个有primary key的 magmaap 表, magma 内部自动实现了压缩。
CREATE TABLE rank3 (id int, rank int, year smallint,gender char(1), count int,primary key(id) ) format 'magmaap';
数据存储说明
特性 |
ROW |
ORC |
Hudi |
MAGMAAP |
|---|---|---|---|---|
行/列存储 |
行 |
行列混合存储 |
行列混合存储 |
行列混合存储 |
存储格式 |
自定义存储格式 |
兼容标准 ORC 格式 |
兼容Apache Hudi表格式 |
自定义存储格式 |
是否支持新执行器 |
不支持 |
支持 |
支持 |
支持 |
压缩 |
支持SNAPPY, ZLIB |
支持LZ4, SNAPPY, ZSTD, ZLIB |
支持LZ4, SNAPPY, ZSTD, ZLIB |
自动选择压缩算法, 不需要用户指定 |
是否UPDATE/DELTE |
支持 |
支持 |
支持 |
支持 |
是否INDEX |
不支持 |
不支持 |
不支持 |
支持 |
创建S3内表#
OushuDB 支持S3内表的ORC格式,创建S3内表的例子如下:
# 如果default_table_format不是s3
1. 当前所在database所属的tablespace是s3的tablespace
CREATE TABLE test(id int)with(appendonly = true, orientation = orc);
2. 当前所在database所属的tablespace不是s3的tablespace,需要建表的时候指定tablespace为s3
CREATE TABLE test(id int)with(appendonly = true, orientation = orc)tablespace s3_default;
# 如果default_table_format是s3
1. 当前所在database所属的tablespace是s3的tablespace
CREATE TABLE test(id int);
2. 当前所在database所属的tablespace不是s3的tablespace,需要建表的时候指定tablespace为s3
CREATE TABLE test(id int)tablespace s3_default;
表的分布#
在OushuDB中,表可以两种方式分布方式:基于 Hash 的分布和 Random 分布。基于 Hash 的分布方法基于分布列的 Hash 值进行分布,Random 分布采取随机分布模式。MagmaAP 兼具了 Hash 分布和 Random 分布的优点,不再显示地支持 Random 分布。其他格式支持两种分布格式。
创建表时用户不指定分布方式的时候非 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 的话,系统默认使用 VC 属性值 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 的 bucketnum 由配置文件 magma-topology.yaml 中 num_ranges 参数决定。
创建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 分布的表。
MagmaAP 表具备的 Hash 和 random 表的优势,通过 VC 属性值 magma_hash_table_nvseg_perseg 来控制每个节点能启动的virtual segment数。 在系统扩容后不需要重新分布数据。
Hash 分布的表 bucketnum 的选取#
针对 Hash 分布的表,bucketnum 决定了一个查询的并行度。在一些常见的硬件配置中(128G内存和12块SAS盘),我们建议选取6 * 节点数或者8 * 节点数。 硬件更好的话可以增加 bucketnum。在系统初始化 的时候,default_hash_table_bucket_number 的初始化默认值为8 * 节点数。
Hash 分布键的选取#
在选择分布键的时候, 我们要考虑用户的应用场景。当进行两表连接的时候,如果连接条件发生在分布键上,那么相同的数据就在同一个数据节点,数据不需要重新进行分布。对于大数据量的表,要参考用户的查询来优化分布键。 同时,分布式系统希望数据均匀地分布在各个节点, 这样各个节点均匀地使用资源,避免出现单个节点处理很慢的场景。所以我们还要根据数据特点来选择,使得数据均匀分布。
下面的语句可以查看一个表的数据分布
SELECT gp_segment_id, count(*) as cnt FROM rank GROUP BY gp_segment_id;
其中gp_segment_id是对于segment 的唯一标识,这样列出了rank 表在每个segment上的数据个数, 从而看到数据是否均匀分布。