记一次 ClickHouse 表级数据迁移操作
📋 背景
一次磁盘满,使用了新的 ck , 换了数据目录,稳定跑一段时间后,需要同步旧数据到新的 ck
🏗️ 环境概览
| 项目 |
旧服务 |
新服务 |
| 容器名 |
old-myproject-clickhouse |
myproject-clickhouse |
| 状态 |
Up 12 days (healthy) |
Up 12 minutes (healthy) |
| HTTP 端口 |
8123 (内部) |
8123 映射至 8323,9000 映射至 9300 |
| Native 端口 |
9000 |
9000 |
🔧 操作步骤
第一步:网络连通
将旧容器连接到新容器所在的 Docker 网络,确保两者网络互通:
1
| docker network connect myproject-network old-myproject-clickhouse
|
为什么要连接网络?
ClickHouse 的 remote() 函数需要跨实例访问数据,网络连通是前提条件。
第二步:进入新服务客户端
1 2
| docker exec -it myproject-clickhouse bash clickhouse-client --user default --password <CHANGE_ME> --database myproject-clickhouse
|
第三步:调整性能参数
1 2 3
| SET max_threads = 16; SET max_insert_threads = 8; SET max_memory_usage = 0;
|
| 参数 |
值 |
说明 |
max_threads |
16 |
并行查询的最大线程数 |
max_insert_threads |
8 |
并行写入的最大线程数 |
max_memory_usage |
0 |
0 表示不限制内存使用,避免迁移时 OOM |
第四步:停止合并任务
1
| SYSTEM STOP MERGES `myproject-clickhouse`.observability_spans;
|
为什么要停止合并?
在数据导入期间禁止 MergeTree 表的合并操作,可以显著提升写入性能,避免后台合并与数据插入抢占资源。
第五步:远程写入数据
1 2 3 4 5 6 7 8 9
| INSERT INTO `myproject-clickhouse`.observability_spans SELECT * FROM remote( 'old-myproject-clickhouse:9000', 'myproject-clickhouse', 'observability_spans', 'default', '<CHANGE_ME>' );
|
第六步:恢复合并 & 优化
1 2 3
| SYSTEM START MERGES `myproject-clickhouse`.observability_spans;
OPTIMIZE TABLE `myproject-clickhouse`.observability_spans FINAL;
|
为什么要 OPTIMIZE?
- 恢复合并后,后台会重新处理 part 文件
OPTIMIZE FINAL 强制立即触发一次完整合并,清理碎片,提升查询性能
⚡ 性能优化要点总结
1 2 3 4 5 6 7 8
| ┌─────────────────────────────────────────────────┐ │ 迁移优化策略 │ ├─────────────────────────────────────────────────┤ │ ① 停止合并 → 消除后台 Merge 资源竞争 │ │ ② 调高线程数 → 充分利用 CPU 并行能力 │ │ ③ 取消内存限制 → 允许大批次数据写入 │ │ ④ 完成后 OPTIMIZE → 整理碎片 + 减少 part 数量 │ └─────────────────────────────────────────────────┘
|
⚠️ 注意事项
- 网络连通性 — 迁移前务必确认两个 ClickHouse 实例网络互通
- 数据一致性 — 建议在业务低峰期操作,或先停止写入端
- 磁盘空间 — 确保目标服务有足够存储空间接收数据
- 迁移后验证 — 可通过
SELECT count() FROM table 对比数据量
📊 效果
通过以上配置,ClickHouse 在迁移过程中能以最大性能运行,迁移完成后通过 OPTIMIZE TABLE 整理数据,确保新服务快速进入最优查询状态。