一、数据划分
Doris支持单分区和复合分区两种建表方式。
在复合分区中:
- 第一级称为 Partition,即分区。用户可以指定某一维度列作为分区列(当前只支持整型和时间类型的列),并指定每个分区的取值范围。
- 第二级称为 Distribution,即分桶。用户可以指定一个或多个维度列以及桶数对数据进行 HASH 分布。
1、以下场景推荐使用复合分区
- 有时间维度或类似带有有序值的维度,可以以这类维度列作为分区列。分区粒度可以根据导入频次、分区数据量等进行评估。
- 历史数据删除需求:如有删除历史数据的需求(比如仅保留最近N 天的数据)。使用复合分区,可以通过删除历史分区来达到目的。也可以通过在指定分区内发送 DELETE 语句进行数据删除。
- 解决数据倾斜问题:每个分区可以单独指定分桶数量。如按天分区,当每天的数据量差异很大时,可以通过指定分区的分桶数,合理划分不同分区的数据,分桶列建议选择区分度大的列。
- 用户也可以不使用复合分区,即使用单分区。则数据只做 HASH 分布。
下面以聚合模型为例,分别演示两种分区的建表语句。
- Partition
-
- Bucket
- PROPERTIES
- ENGINE
2、关于 Partition 和 Bucket 的数量和数据量的建议
- 一个表的 Tablet 总数量等于 (Partition num * Bucket num)。
- 一个表的 Tablet 数量,在不考虑扩容的情况下,推荐略多于整个集群的磁盘数量。
- 单个 Tablet 的数据量理论上没有上下界,但建议在 1G – 10G 的范围内。如果单个 Tablet 数据量过小,则数据的聚合效果不佳,且元数据管理压力大。如果数据量过大,则不利于副本的迁移、补齐,且会增加 Schema Change 或者 Rollup 操作失败重试的代价(这些操作失败重试的粒度是 Tablet)。
- 当 Tablet 的数据量原则和数量原则冲突时,建议优先考虑数据量原则。
- 在建表时,每个分区的 Bucket 数量统一指定。但是在动态增加分区时(ADD PARTITION),可以单独指定新分区的 Bucket 数量。可以利用这个功能方便的应对数据缩小或膨胀。
- 一个 Partition 的 Bucket 数量一旦指定,不可更改。所以在确定 Bucket 数量时,需要预先考虑集群扩容的情况。比如当前只有 3 台 host,每台 host 有 1 块盘。如果 Bucket 的数量只设置为 3 或更小,那么后期即使再增加机器,也不能提高并发度。
- 举一些例子:假设在有10台BE,每台BE一块磁盘的情况下。如果一个表总大小为 500MB,则可以考虑4-8个分片。5GB:8-16个。50GB:32个。500GB:建议分区,每个分区大小在 50GB 左右,每个分区16-32个分片。5TB:建议分区,每个分区大小在 50GB 左右,每个分区16-32个分片。
注:表的数据量可以通过 show data 命令查看,结果除以副本数,即表的数据量。
二、演示单分区和复合分区
1、单分区
建立一个名字为 table1 的逻辑表。分桶列为 siteid,桶数为 10。
这个表的 schema 如下:
- siteid:类型是INT(4字节), 默认值为10
- citycode:类型是SMALLINT(2字节)
- username:类型是VARCHAR, 最大长度为32, 默认值为空字符串
- pv:类型是BIGINT(8字节), 默认值是0; 这是一个指标列, Doris内部会对指标列做聚合操作, 这个列的聚合方法是求和(SUM)
建表语句如下:
CREATE TABLE table1
(
siteid INT DEFAULT '10',
citycode SMALLINT,
username VARCHAR(32) DEFAULT '',
pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(siteid, citycode, username)
DISTRIBUTED BY HASH(siteid) BUCKETS 10
PROPERTIES("replication_num" = "1");
将 table1_data 导入 table1 中:vim table1_data
10,101,jim,2
11,101,grace,2
12,102,tom,2
13,102,bush,3
14,103,helen,3
curl --location-trusted -u root:123456 -H "label:table1_20210210" -H "column_separator:," -T table1_data http://node1:8030/api/test_db/table1/_stream_load
select * from table1;
2、 复合分区
建立一个名字为 table2 的逻辑表。
这个表的 schema 如下:
- event_day:类型是DATE,无默认值
- siteid:类型是INT(4字节), 默认值为10
- citycode:类型是SMALLINT(2字节)
- username:类型是VARCHAR, 最大长度为32, 默认值为空字符串
- pv:类型是BIGINT(8字节), 默认值是0; 这是一个指标列, Doris 内部会对指标列做聚合操作, 这个列的聚合方法是求和(SUM)
我们使用 event_day 列作为分区列,建立3个分区: p202006, p202007, p202008
-
- p202006:范围为 [最小值, 2020-07-01)
- p202007:范围为 [2020-07-01, 2020-08-01)
- p202008:范围为 [2020-08-01, 2020-09-01)
注意区间为左闭右开。
每个分区使用 siteid 进行哈希分桶,桶数为10
建表语句如下:
CREATE TABLE table2
(
event_day DATE,
siteid INT DEFAULT '10',
citycode SMALLINT,
username VARCHAR(32) DEFAULT '',
pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(event_day, siteid, citycode, username)
PARTITION BY RANGE(event_day)
(
PARTITION p202006 VALUES LESS THAN ('2020-07-01'),
PARTITION p202007 VALUES LESS THAN ('2020-08-01'),
PARTITION p202008 VALUES LESS THAN ('2020-09-01')
)
DISTRIBUTED BY HASH(siteid) BUCKETS 10
PROPERTIES("replication_num" = "1");
将 table2_data 导入 table2 中:vim table2_data
2020-07-03|11|1|jim|2
2020-07-05|12|1|grace|2
2020-07-12|13|2|tom|2
2020-07-15|14|3|bush|3
2020-07-12|15|3|helen|3
curl --location-trusted -u root:123456 -H "label:table2_20200707" -H "column_separator:|" -T table2_data http://node1:8030/api/test_db/table2/_stream_load
select * from table2;
注意事项:
- 上述表通过设置 replication_num 建的都是单副本的表,Doris建议用户采用默认的 3 副本设置,以保证高可用。
- 可以对复合分区表动态的增删分区。详见 HELP ALTER TABLE 中 Partition 相关部分。
- 数据导入可以导入指定的 Partition。详见 HELP LOAD。
- 可以动态修改表的 Schema。
- 可以对 Table 增加上卷表(Rollup)以提高查询性能,这部分可以参见高级使用指南关于 Rollup 的描述。
- 表的列的Null属性默认为true,会对查询性能有一定的影响。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容