ALTER 修改列结构
ClickHouse 的表结构变更用 ALTER TABLE 完成:加列、删列、改类型、改默认值、加跳过索引。多数变更对新数据立即生效,但涉及旧数据的部分——类型转换、索引回填——会以 mutation 的形式在后台异步执行,大表上耗时可能很长,因此变更前要看 mutation 队列与磁盘余量。
基本信息
| 常用语句 | ADD COLUMN / DROP COLUMN / MODIFY COLUMN / RENAME COLUMN / COMMENT COLUMN |
|---|---|
| 跳过索引 | ADD INDEX TYPE minmax|set|bloom_filter GRANULARITY n,MATERIALIZE INDEX 回填 |
| 生效范围 | 新结构立即对新数据生效,旧数据的转换与索引回填由 mutation 完成 |
| 进度查看 | system.mutations 查未完成任务,KILL MUTATION 可终止 |
| 幂等写法 | IF EXISTS / IF NOT EXISTS 便于脚本重复执行 |
典型使用场景
- 版本迭代新增字段,并给旧数据一个默认值
- 把 String 字段改为 LowCardinality 降低存储与内存开销
- 为高频过滤字段补建跳过索引,并按需回填历史数据
- 删除废弃字段,先停写观察一段时间后再清理
- 运维脚本中用 IF NOT EXISTS 保证可重复执行
常用变更语句
常用变更语句
-- 加列:AFTER 指定位置,默认值即取即算、不回写旧 part
ALTER TABLE events ADD COLUMN IF NOT EXISTS device String DEFAULT 'unknown' AFTER user_id;
-- 改类型:对旧数据是异步 mutation,大表上耗时较长
ALTER TABLE events MODIFY COLUMN device LowCardinality(String);
-- 删除列:磁盘空间要等 part 重写清理后才回收
ALTER TABLE events DROP COLUMN IF EXISTS legacy_col;
-- 跳过索引:先加定义,再回填已有数据
ALTER TABLE events ADD INDEX idx_user user_id TYPE bloom_filter GRANULARITY 4;
ALTER TABLE events MATERIALIZE INDEX idx_user;
-- 观察变更进度与失败原因
SELECT table, mutation_id, command, is_done, latest_fail_reason
FROM system.mutations WHERE is_done = 0;各类变更的行为
| 语句 | 对新数据 | 对旧数据 |
|---|---|---|
| ADD COLUMN | 立即生效 | 不重写;带 DEFAULT 表达式时读取即计算 |
| MODIFY COLUMN 改类型 | 立即生效 | 异步 mutation 转换,大表耗时长 |
| DROP COLUMN | 立即生效 | 不立即释放磁盘,等 part 重写清理 |
| RENAME COLUMN | 立即生效 | 纯元数据操作,几乎瞬时完成 |
| ADD INDEX | 新 part 自动带索引 | 需 MATERIALIZE INDEX 回填,属 mutation |
ADD COLUMN 配 DEFAULT 表达式时,读旧数据会即时计算默认值而不落盘,开销可控,这也是加列比改类型安全得多的原因。
RENAME COLUMN 是纯元数据操作,几乎瞬时完成且不触发 mutation;批量调整字段命名优先用它,而不是新建列再把数据搬过去,后者会引发大范围 part 重写。