避免 Optimize Final
使用 MergeTree 引擎 的 ClickHouse 表将数据以 不可变的部分 形式存储在磁盘上,每次插入数据时都会创建这些部分。
每次插入都会创建一个新的部分,其中包含排序、压缩的列文件,以及索引和校验和等元数据。有关部分结构以及它们如何形成的详细描述,我们建议您阅读此 指南。
随着时间的推移,后台进程会将较小的部分合并成较大的部分,以减少碎片并提高查询性能。
虽然手动触发此合并很诱人,使用
但大多数情况下,您应该避免使用 OPTIMIZE FINAL 操作,因为它会启动资源密集型操作,可能会影响集群性能。
OPTIMIZE FINAL 与 FINAL
OPTIMIZE FINAL 与 FINAL 不同,有时需要使用 FINAL 来获取没有重复的结果,例如使用 ReplacingMergeTree。通常,如果您的查询过滤的列与主键中的列相同,则可以使用 FINAL。
为什么避免?
代价高昂
运行 OPTIMIZE FINAL 会强制 ClickHouse 将 所有 活动部分合并成 单个部分,即使已经发生了大型合并。这涉及
- 解压缩 所有部分
- 合并 数据
- 再次压缩 它
- 将最终部分写入磁盘或对象存储
这些步骤是 CPU 和 I/O 密集型 的,并且会对您的系统造成重大压力,尤其是在涉及大型数据集时。
它忽略安全限制
通常,ClickHouse 避免合并大于 ~150 GB 的部分(可通过 max_bytes_to_merge_at_max_space_in_pool 进行配置)。但 OPTIMIZE FINAL 忽略此保护措施,这意味着
- 它可能会尝试将 多个 150 GB 的部分 合并成一个巨大的部分
- 这可能会导致 长时间的合并时间、内存压力,甚至 内存不足错误
- 这些大型部分可能难以合并,即由于上述原因,进一步合并它们的尝试可能会失败。在需要正确查询时间行为的情况下,这可能会导致不良后果,例如 ReplacingMergeTree 累积重复项,从而降低查询时间性能。
让后台合并完成工作
ClickHouse 已经执行智能后台合并来优化存储和查询效率。这些是增量的、资源感知的,并且尊重配置的阈值。除非您有特定的需求(例如,在冻结表或导出之前完成数据),否则 最好让 ClickHouse 自行管理合并。