Bucket table 说明
在 ByConity 中使用 Bucket table 时,系统会依据用户建表语句中提供的一个或者多个列、表达式整理表数据,将相同值的数据聚簇在同一个 bucket number 下。
使用 Bucket table 的收益
使用 cluster key 聚蔟数据在大表上可以获得以下几项收益:
- 针对 cluster key 的点查可以过滤掉大部分数据,降低 IO 量获得更短的执行时间和更高的并发 QPS
- 针对 cluster key 的聚合计算,计算节点可以在数据子集进行预先计算,实现更小的内存占用和更短的执行时间
- 两张或者多张表针对 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 值数量,鉴于
- 相同 cluster key 的数据会归属于同一个 bucket number
- 一个 bucket number 下的所有 parts 会发送到同一个 worker 中进行计算
我们可以得出结论
- 为了能利用所有 worker 节点进行计算,distinct 值需要至少超过 worker 数量
- 如果 distinct 值数量较小,偏向于选择最大的 distinct 值,最好为 worker 数量的倍数,以实现查询时数据分布的更均衡
例如:
- 表 test,用户常用的过滤列是 c1, c2, c3,列相互独立
- worker 数量为 30
- distinct c1 为 6
- distinct c2 为 8
- distinct c3 为 5
可以看出 3 列单独的 distinct 都小于 worker 数量。disticnt c1, c2 为 48 虽然大于 worker 数量,但是不是 worker 数量的倍数,因此也不是合适的 cluster key。distinct c1, c3 为 30 正好为 worker 数量的 1 倍,但考虑数据分布的均衡性,选择更大的 distinct c1, c2, c3 为 8 倍 worker 数量更为合适
如何选择 bucket number
鉴于在一个分区内
- 每行数据会依据 cluster key 的值按
% BUCKETS
计算得到相应 bucket number - 同一个 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 by 定义的情况:
- 修改 cluster key
- 此时意味着当前的数据已经无法获得 bucket table 收益,因此无需考虑 recluster 期间失去的收益
- 需要评估 recluster 任务对于现有任务的影响判断是否可以执行
- 修改 bucket number
- 当前 bucket table 的收益仍在,因此需要和业务方确认可以接受的性能回退的时间,进一步根据 recluster 时间判断是否可以执行,以及确定开始执行时间
- 也需要评估 recluster 任务对于现有任务的影响判断是否可以执行