数据分区( partition
)和数据分片( shard
)是完全不同的两个概念。数据分区是针对本地数据库而言的,是数据的一种横向切分。数据分区对于一款 OLAP
数据库而言意义非凡:借助数据分区,在后续的查询过程中能够跳过不必要的数据目录,从而提升查询的性能。合理地利用分区特性,还可以变相实现数据的更新操作,因为数据分区支持删除、替换和重置操作。假设数据表按照月份分区,那么数据就可以按月份的粒度被替换更新。
分区虽好,但不是所有的表引擎都可以使用这种特性,目前只有合并树( MergeTree
)家族系列的表引擎才支持数据分区。接下来通过一个简单的例子演示分区表的使用方法。首先由 PARTITION BY
指定分区键,例如下面的数据表 partition_v1
使用了日期字段作为分区键,并将其格式化成年月的形式:
$ CREATE TABLE partition_v1 ( ID String, URL String, EventTime Date ) ENGINE = MergeTree() PARTITION BY toYYYYMM(EventTime) ORDER BY ID;点击复制复制失败已复制
接着写入不同月份的测试数据:
$ INSERT INTO partition_v1 VALUES ('A000', 'www.baidu.com', '2022-04-01'), ('A001', 'www.virtualbing.fun', '2022-05-01');点击复制复制失败已复制
最后通过 system.parts
系统表,查询数据表的分区状态:
$ SELECT table, partition, path FROM system.parts WHERE table = 'partition_v1'; ┌─table────────┬─partition─┬─path─────────────────────────────────────────────────────────────────────────────┐ │ partition_v1 │ 202204 │ /var/lib/clickhouse/store/4b2/4b2ae9a7-ec2d-4e5b-828d-e6fbe5a2451d/202204_1_1_0/ │ │ partition_v1 │ 202205 │ /var/lib/clickhouse/store/4b2/4b2ae9a7-ec2d-4e5b-828d-e6fbe5a2451d/202205_2_2_0/ │ └──────────────┴───────────┴──────────────────────────────────────────────────────────────────────────────────┘点击复制复制失败已复制
可以看到, partition_v1
按年月划分后,目前拥有两个数据分区,且每个分区都对应一个独立的文件目录,用于保存各自部分的数据。
合理设计分区键非常重要,通常会按照数据表的查询场景进行针对性设计。例如在刚才的示例中数据表按年月分区,如果后续的查询按照分区过滤,例如:
$ SELECT * FROM partition_v1 WHERE EventTime = '2022-05-01';点击复制复制失败已复制
那么在后续的查询过程中,可以利用分区索引跳过 4
月份的分区目录,只加载 5
月份的数据,从而带来查询的性能提升。
当然,使用不合理的分区键也会适得其反,分区键不应该使用粒度过细的数据字段。例如,按照小时分区,将会带来分区数量的急剧增长,从而导致性能下降。