最近项目在尝试 ClickHouse 集群部署,但是我们在做 ETL 的时候,有个表想着为了加快响应速度,建立了分区,所以对分区知识进行了二次调研。

重要结论

首先分区并不能加快查询速度,而更加适用于更新或者删除数据用。

分区数量限制by max_partitions_per_insert_block 控制,默认是 100。当插入数据到 100 以上的时候,会报错:

1
2
3
4
5
6
7
8
DB::Exception: Too many partitions for single INSERT block (more than 100). 
The limit is controlled by 'max_partitions_per_insert_block' setting.
Large number of partitions is a common misconception.
It will lead to severe negative performance impact,
including slow server startup, slow INSERT queries and slow SELECT queries.
Recommended total number of partitions for a table is under 1000..10000.
Please note, that partitioning is not intended to speed up SELECT queries (ORDER BY key is sufficient to make range queries fast).
Partitions are intended for data manipulation (DROP PARTITION, etc)..

分区的特性

  • 分区只能在 MergeTree 引擎下使用
  • 分区不会对分片造成影响

分区是表的分区,具体的 DDL 操作关键词是 PARTITION BY,指的是一个表按照某一列数据(比如日期)进行分区,对应到最终的结果就是不同分区的数据会写入不同的文件中。

分片复用了数据库的分区,相当于在原有的分区下,作为第二层分区,是在不同节点/机器上的体现。

下面这张图展示了 ClickHouse 的分区和分片的关系:

在分布式模式下,ClickHouse 会将数据分为多个分片,并且分布到不同节点上。

查看数据分布情况

创建完分区,插入好数据,执行如下 SQL 可以看到数据分布情况:

1
2
3
SELECT database, table, partition, partition_id, name, path 
FROM system.parts
WHERE table='xxx';

数据文件命名规则为:PartitionID_MinBlockNum_MaxBlockNum_Level

总结:ClickHouse 分区适用的场景

  • 在 partition key 上进行分区裁剪,只查询必要的数据
  • 对 partition 进行 TTL 管理,淘汰过期的分区数据