Doris分区与分桶(八)

接上篇----------Doris 建表示例

Doris 支持两层的数据划分。第一层是 Partition,支持 Range 和 List 的划分方式。第二层是 Bucket(Tablet),仅支持 Hash 的划分方式。

也可以仅使用一层分区。使用一层分区时,只支持 Bucket 划分。

Partition
  • Partition 列可以指定一列或多列。分区类必须为 KEY 列。

  • 不论分区列是什么类型,在写分区值时,都需要加双引号。

  • 分区数量理论上没有上限。

  • 当不使用 Partition 建表时,系统会自动生成一个和表名同名的,全值范围的Partition。该 Partition 对用户不可见,并且不可删改。

Range 分区

分区列通常为时间列,以方便的管理新旧数据。不可添加范围重叠的分区。 Partition 指定范围的方式

VALUES LESS THAN (...) 仅指定上界,系统会将前一个分区的上界作为该分区的下界,生成一个左闭右开的区间。分区的删除不会改变已存在分区的范围。删除分区可能出现空洞。

VALUES [...) 指定同时指定上下界,生成一个左闭右开的区间。

通过 VALUES [...) 同时指定上下界比较容易理解。这里举例说明,当使用 VALUES LESS THAN (...) 语句进行分区的增删操作时,分区范围的变化情况:

(1)如上 expamle_range_tbl 示例,当建表完成后,会自动生成如下 3 个分区:

p201701: [MIN_VALUE, 2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201703: [2017-03-01, 2017-04-01)

(2)增加一个分区 p201705 VALUES LESS THAN ("2017-06-01"),分区结果如下:

p201701: [MIN_VALUE, 2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201703: [2017-03-01, 2017-04-01)
p201705: [2017-04-01, 2017-06-01)

(3)此时删除分区 p201703,则分区结果如下:

p201701: [MIN_VALUE, 2017-02-01)
p201702: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)

注意到 p201702 和 p201705 的分区范围并没有发生变化,而这两个分区之间,出现了一个空洞:[2017-03-01, 2017-04-01)。即如果导入的数据范围在这个空洞范围内,是无法导入的。

(4)继续删除分区 p201702,分区结果如下:

p201701: [MIN_VALUE, 2017-02-01)
p201705: [2017-04-01, 2017-06-01)

空洞范围变为:[2017-02-01, 2017-04-01)

(5)现在增加一个分区 p201702new VALUES LESS THAN ("2017-03-01"),分区结果如下:

p201701: [MIN_VALUE, 2017-02-01)
p201702new: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)

可以看到空洞范围缩小为:[2017-03-01, 2017-04-01)

(6)现在删除分区 p201701,并添加分区 p201612 VALUES LESS THAN ("2017-01-01"),分区结果如下:

p201612: [MIN_VALUE, 2017-01-01)
p201702new: [2017-02-01, 2017-03-01)
p201705: [2017-04-01, 2017-06-01)

即出现了一个新的空洞:[2017-01-01, 2017-02-01)

List 分区

分 区 列支 持 BOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, DATE, DATETIME, CHAR, VARCHAR 数据类型,分区值为枚举值。只有当数据为目标分区枚举值

其中之一时,才可以命中分区。不可添加范围重叠的分区。

Partition 支持通过 VALUES IN (...) 来指定每个分区包含的枚举值。下面通过示例说明,进行分区的增删操作时,分区的变化。

(1)如上 example_list_tbl 示例,当建表完成后,会自动生成如下 3 个分区:

p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "San Francisco")
p_jp: ("Tokyo")

(2)增加一个分区 p_uk VALUES IN ("London"),分区结果如下:

p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "San Francisco")
p_jp: ("Tokyo")
p_uk: ("London")

(3)删除分区 p_jp,分区结果如下:

p_cn: ("Beijing", "Shanghai", "Hong Kong")
p_usa: ("New York", "San Francisco")
p_uk: ("London")

Bucket

(1)如果使用了 Partition,则 DISTRIBUTED ... 语句描述的是数据在各个分区内的划分规则。如果不使用 Partition,则描述的是对整个表的数据的划分规则。

(2)分桶列可以是多列,但必须为 Key 列。分桶列可以和 Partition 列相同或不同。

(3)分桶列的选择,是在 查询吞吐 和 查询并发 之间的一种权衡:

  • ① 如果选择多个分桶列,则数据分布更均匀。如果一个查询条件不包含所有分桶列的等值条件,那么该查询会触发所有分桶同时扫描,这样查询的吞吐会增加,单个查询的延迟随之降低。这个方式适合大吞吐低并发的查询场景。

  • ② 如果仅选择一个或少数分桶列,则对应的点查询可以仅触发一个分桶扫描。此时,当多个点查询并发时,这些查询有较大的概率分别触发不同的分桶扫描,各个查询之间的 IO 影响较小(尤其当不同桶分布在不同磁盘上时),所以这种方式适合高并发的点查询场景。

(4)分桶的数量理论上没有上限。

使用复合分区的场景

以下场景推荐使用复合分区

(1)有时间维度或类似带有有序值的维度,可以以这类维度列作为分区列。分区粒度可以根据导入频次、分区数据量等进行评估。

(2)历史数据删除需求:如有删除历史数据的需求(比如仅保留最近 N 天的数据)。使用复合分区,可以通过删除历史分区来达到目的。也可以通过在指定分区内发送 DELETE 语句进行数据删除。

(3)解决数据倾斜问题:每个分区可以单独指定分桶数量。如按天分区,当每天的数据量差异很大时,可以通过指定分区的分桶数,合理划分不同分区的数据,分桶列建议选择区分度大的列。

多列分区

Doris 支持指定多列作为分区列,示例如下:

1)Range 分区
PARTITION BY RANGE(`date`, `id`)
(
 PARTITION `p201701_1000` VALUES LESS THAN ("2017-02-01", "1000"),
 PARTITION `p201702_2000` VALUES LESS THAN ("2017-03-01", "2000"),
 PARTITION `p201703_all` VALUES LESS THAN ("2017-04-01")
)

指定 date(DATE 类型) 和 id(INT 类型) 作为分区列。以上示例最终得到的分区如下:

p201701_1000: [(MIN_VALUE, MIN_VALUE), ("2017-02-01", "1000") )
p201702_2000: [("2017-02-01", "1000"), ("2017-03-01", "2000") )
p201703_all: [("2017-03-01", "2000"), ("2017-04-01", MIN_VALUE))

注意,最后一个分区用户缺省只指定了 date 列的分区值,所以 id 列的分区值会默认填充 MIN_VALUE。当用户插入数据时,分区列值会按照顺序依次比较,最终得到对应的分区。举例如下:

数据 --> 分区
2017-01-01, 200 --> p201701_1000
2017-01-01, 2000 --> p201701_1000
2017-02-01, 100 --> p201701_1000
2017-02-01, 2000 --> p201702_2000
2017-02-15, 5000 --> p201702_2000
2017-03-01, 2000 --> p201703_all
2017-03-10, 1 --> p201703_all
2017-04-01, 1000 --> 无法导入
2017-05-01, 1000 --> 无法导入
2)List 分区
PARTITION BY LIST(`id`, `city`)
(
 PARTITION `p1_city` VALUES IN (("1", "Beijing"), ("1", "Shanghai")),
 PARTITION `p2_city` VALUES IN (("2", "Beijing"), ("2", "Shanghai")),
 PARTITION `p3_city` VALUES IN (("3", "Beijing"), ("3", "Shanghai"))
)

指定 id(INT 类型) 和 city(VARCHAR 类型) 作为分区列。最终得到的分区如下:

p1_city: [("1", "Beijing"), ("1", "Shanghai")]
p2_city: [("2", "Beijing"), ("2", "Shanghai")]
p3_city: [("3", "Beijing"), ("3", "Shanghai")]

当用户插入数据时,分区列值会按照顺序依次比较,最终得到对应的分区。举例如下:

数据 ---> 分区
1, Beijing ---> p1_city
1, Shanghai ---> p1_city
2, Shanghai ---> p2_city
3, Beijing ---> p3_city
1, Tianjin ---> 无法导入
4, Beijing ---> 无法导入

接下篇----------Doris的PROPERTIES与ENGINE

相关推荐
武子康18 小时前
大数据-257 离线数仓 - 数据质量监控 监控方法 Griffin架构
java·大数据·数据仓库·hive·hadoop·后端
莹雨潇潇18 小时前
Hadoop完全分布式环境部署
大数据·hadoop·分布式
学计算机的睿智大学生1 天前
Hadoop集群搭建
大数据·hadoop·分布式
m0_748254881 天前
DataX3.0+DataX-Web部署分布式可视化ETL系统
前端·分布式·etl
清平乐的技术专栏1 天前
Hive SQL 查询所有函数
hive·hadoop·sql
节点。csn2 天前
Hadoop yarn安装
大数据·hadoop·分布式
不惑_2 天前
小白入门 · 腾讯云轻量服务器部署 Hadoop 3.3.6
服务器·hadoop·腾讯云
csding112 天前
写入hive metastore报问题Permission denied: user=hadoop,inode=“/user/hive”
数据仓库·hive·hadoop