选择分区键
分区主要是一种数据管理技术,而不是查询优化工具,虽然它可以在特定工作负载中提高性能,但它不应该是加速查询的第一种机制;分区键必须谨慎选择,清晰理解其影响,只有在与数据生命周期需求或清晰理解的访问模式相一致时才应用。
在 ClickHouse 中,分区根据指定的键将数据组织成逻辑段。这是在创建表时使用 PARTITION BY
子句定义的,通常用于按时间间隔、类别或其他业务相关维度分组行。每个分区表达式的唯一值在磁盘上形成自己的物理分区,而 ClickHouse 为每个这些值存储数据于单独的部分。分区改善了数据管理,简化了保留策略,并可以帮助处理特定的查询模式。
例如,考虑以下以 toStartOfMonth(date)
作为分区键的英国价格数据集表。
每当一组行被插入到表中时,ClickHouse 会为插入的行中每个唯一分区键值创建一个新的数据部分,而不是创建一个包含所有插入行的单一数据部分(至少 [/operations/settings/settings#max_insert_block_size])(如这里所述):

ClickHouse 服务器首先根据分区键值 toStartOfMonth(date)
将上面图示中示例插入的4行进行分割。然后,对于每个识别出的分区,这些行按照正常的步骤处理,依次执行多个顺序步骤(① 排序, ② 拆分为列, ③ 压缩, ④ 写入磁盘)。
有关分区的更详细说明,我们推荐本指南。
启用分区后,ClickHouse 仅在内部合并数据部分,而不跨分区进行合并。我们为上面的示例表进行了概述:

分区的应用
分区是管理 ClickHouse 中大型数据集的强大工具,尤其是在可观察性和分析用例中。它通过允许在单一元数据操作中删除、移动或归档整个分区(通常与时间或业务逻辑对齐),实现高效的数据生命周期操作。这比逐行删除或复制操作要快得多且资源消耗更少。分区还与 ClickHouse 的 TTL 和分级存储等功能无缝集成,使得可以在不需要自定义编排的情况下实施保留策略或冷热存储策略。例如,最近的数据可以保留在快速的 SSD 存储上,而较旧的分区会自动移动到更便宜的对象存储中。
虽然分区可以提高某些工作负载的查询性能,但它也可能对响应时间产生负面影响。
如果分区键不在主键中并且您正在按此键过滤,用户可能会发现查询性能有所提升。有关示例,请参见这里。
相反,如果查询需要跨分区查询,由于总部分数的增加,性能可能会受到负面影响。因此,用户在考虑将分区作为查询优化技术之前,应理解他们的访问模式。
总之,用户应主要将分区视为一种数据管理技术。有关管理数据的示例,请参阅可观察性用例指南中的"管理数据"和核心概念 - 数据表分区中的"表分区用于什么?"。
选择低基数的分区键
重要的是,部分数量的增加会对查询性能产生负面影响。因此,如果部分数量超过总计或每个分区规定的限制,ClickHouse 将对插入作出“部分过多” [/knowledgebase/exception-too-many-parts] 的响应错误。
为分区键选择正确的基数至关重要。高基数分区键 - 即不同分区值的数量较大 - 可能导致数据部分的激增。由于 ClickHouse 不会跨分区合并部分,分区过多将导致过多的未合并部分,最终触发“部分过多”错误。合并是必需的,以减少存储碎片并优化查询速度,但对于高基数的分区,这种合并潜力就会丧失。
相比之下,一个低基数分区键——具有少于 100 - 1,000 个独特值——通常是最佳选择。它能够高效地合并部分,保持元数据开销较低,并避免在存储中创建过多对象。此外,ClickHouse 会自动在分区列上构建 MinMax 索引,这可以显著加速对这些列过滤的查询。例如,当表按 toStartOfMonth(date)
分区时,按月过滤允许引擎完全跳过不相关的分区及其部分。
虽然分区可以改善某些查询模式的性能,但它主要是一种数据管理特性。在许多情况下,与使用未分区表相比,跨所有分区查询可能会更慢,这主要是由于数据碎片增多和扫描更多部分。谨慎使用分区,并始终确保所选键是低基数并符合您的数据生命周期策略(例如,通过 TTL 进行的保留)。如果您不确定是否需要分区,可以考虑从不使用分区开始,并根据观察到的访问模式进行后续优化。