<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>MergeTree on </title>
    <link>/tags/mergetree/</link>
    <description>Recent content in MergeTree on </description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Fri, 28 Aug 2026 09:30:00 +0800</lastBuildDate><atom:link href="/tags/mergetree/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>在 ClickHouse 上补一列历史数据：一次只读评审</title>
      <link>/posts/clickhouse-column-backfill-mutation-review/</link>
      <pubDate>Fri, 28 Aug 2026 09:30:00 +0800</pubDate>
      
      <guid>/posts/clickhouse-column-backfill-mutation-review/</guid>
      <description>同事发来一份补数方案，让我在执行前帮忙看看。事情不复杂：一张 1300 亿行、19.54 TiB 的 ReplicatedMergeTree 表，有一列连续 18 天被写成了 0，要把这 109 万行改回正确值。
方案主体是对的：用 ALTER TABLE … UPDATE 逐个分区原地改，而不是把正确数据重新 INSERT 一遍。我最后提的意见几乎全落在回滚那一节：它的回滚谓词会连带清掉十万行本来就正确的数据，而且这件事一旦补数跑完就再也查不出来了。下面按我看方案的顺序记。
背景 出问题的是一次上线漏了一行映射代码，placed_at（下单时间）没有被赋值，于是这一列在连续 18 天里都是 0。代码侧已经修好上线，窗口闭合了，剩下的只有历史数据。
表的结构（列名和表名我改写过，键的位置和列数是原样）：
CREATE TABLE analytics.events ( id String, source_id UInt32, placed_at UInt64, -- 出问题的列，毫秒时间戳 settled_at UInt64, -- partition key + primary key 首列 retry_num Int8, ext_id String, group_id String, ... -- 共 39 列 ) ENGINE = ReplicatedMergeTree PARTITION BY toYYYYMMDD(toDateTime(settled_at / 1000)) ORDER BY (settled_at, id, retry_num) SETTINGS storage_policy = &amp;#39;tiered&amp;#39; 几个先交代清楚的前提，后面所有判断都建立在这上面：</description>
    </item>
    
  </channel>
</rss>
