Bucket Table 说明
Bucket table 是 ByteHouse 在建表的时候的一种性能优化选项,在 ByteHouse中使用 Bucket table 时,系统会依据用户建表语句中提供的一个或者多个列、表达式整理表数据,将相同值的数据聚簇在同一个 bucket number 下,从而在查询计算中获得更好的性能。
使用 Bucket Table 的收益
使用 cluster key 聚蔟数据在大表上可以获得以下几项收益:
- 针对 cluster key 的点查可以过滤掉大部分数据,降低IO量获得更短的执行时间和更高的并发QPS。
- 针对 cluster key 的聚合计算,可以有更少的内存占用和更短的执行时间,配合
distributed_perfect_shard
优化可以获得进一步的提高。 - 两张或者多张表针对 cluster key 的 join 可以获得 co-located join 的优化,极大的降低 shuffle 数据量并得到更短的执行时间。
Bucket Table 使用场景
- 表足够大,意味着在一个分区下的parts数量至少需要显著多于 worker(计算节点)数量。
- 查询语句可以从上述收益点中获益。
如何选择分桶键 Cluster Key
Cluster key 可以是一个或者多个列、表达式,建议最多使用3个字段,更多的字段通常会引入过高的写入代价且获益语句范围更小。
选择正确的 cluster key 对于性能的影响非常显著,因此需要慎重选择。通常可以按照如下原则:
- 经常用于相等、IN 过滤的列。
- 常用的聚合列。
- 多表的 join key。
上述场景如果常用的情况是两列组合,比如 a = 1 and b = 2,那么 cluster key 选择两列可以获得更好的效果。
另一个需要考虑的维度是列的 distinct 值数量:
- distinct 值需要至少超过 worker 数量。
- 如果 distinct 值数量较小,最好能保持 worker 数量的倍数,以实现查询时数据分布的更均衡。
如何选择 bucket number
在一个分区内:
- 数据会依据 cluster key 的值分配到相应 bucket number 的 parts文件中。
- 同一个 bucket number 的 parts文件在查询时会发送到同一个 worker节点上计算。
因此选择一个合适的 bucket number 对于存储和查询都有重大的影响,一般有如下原则:
- 确保 bucket number 为 worker 数量的倍数,这是为了保证查询时分配的均衡,一般建议设置为1倍或者2倍(预留扩充worker节点余度)worker节点数量即可。
- 确保一个分区下一个 bucket number 中有足够多的数据,不要生成太小的 parts,因此建议如果表比较小,至少确保一个分区的一个 bucket number parts 大小超过 1GB。不要设置过高的 bucket nubmer,可以出现小于 worker 数量的 bucket number。
如何决定是否要修改 Cluster by 定义
在运行过程中因为数据变化、查询模式变化、worker节点数量变化,用户可能会想要重新设置 cluster key 和 bucket number。
这里需要考虑实施修改的代价,权衡是否需要修改以及何时修改:
- 修改 cluster by 定义需要对现存已有数据做 recluster,需要评估现存数据量估算 recluster 执行时间。
- Recluster 期间现存数据的查询会回退为一张普通表,所有 bucket table 的收益暂时都失去。
- Recluster 会占用 write worker 的资源,需要评估当前cnch集群是否有独立的 write worker 以及当前负担,评估对现有查询、merge等任务的影响。
这里有两种情况:
- 修改 cluster key:
a. 此时意味着当前的数据已经无法获得 bucket table 收益,因此无需考虑 recluster 期间失去的收益。
b. 需要评估 recluster 任务对于现有任务的影响判断是否可以执行。 - 修改 bucket number:
a. 当前 bucket table 的收益仍在,因此需要和业务方确认可以接受的性能回退的时间,进一步根据 recluster 时间判断是否可以执行,以及确定开始执行时间。
b. 也需要评估 recluster 任务对于现有任务的影响判断是否可以执行。
分桶应用案例
假设某 ByteHouse 订阅用户启用了六个计算节点,由于单个分区的数据量较大,超过2亿条记录,应用程序经常根据c1
和c2
字段进行聚合和连接操作。 因此,决定使用桶表进行优化。 桶表的设计选项如下:
- 分桶键( CLUSTER Key )选择:选择
c1
和c2
列作为分桶键。 - 桶(Bucket)数:取节点数的两倍:12。
-- 创建带有分桶的表 create table with bucketing
create or replace table table_01 (c1 timestamp, c2 string, c3 number) cluster by (to_date(c1), c2) INTO 12 BUCKETS;
-- 将桶添加到现有数据中 add bucket to existing data
ALTER TABLE t CLUSTER BY (column, expression, ...) INTO 64 BUCKETS
-- 按多列将桶添加到集群中 add bucket to cluster by multiple columns
ALTER TABLE t CLUSTER BY sipHash(a,b,c) INTO 64 BUCKETS
-- 添加或更改集群属性 Add or change the cluster properties
ALTER TABLE t MODIFY CLUSTER BY (column, expression, ...) INTO 64 BUCKETS