这是《ClickHouse 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Projection 是表内的一种物理投影,可以按不同排序键或聚合形式保存数据,查询时由优化器选择。它适合解决同一张表存在多种查询模式的问题。
14.1 问题背景
主表排序:
ORDER BY (event_date, event_type, city_id, user_id)
适合按日期和事件类型查询,但下面查询效果较弱:
SELECT count()
FROM analytics.events_local
WHERE user_id = 1001;
重新设计排序会影响原有查询。Projection 可以在同一表内保留另一份数据排列。
14.2 普通投影
ALTER TABLE analytics.events_local
ADD PROJECTION proj_user
(
SELECT *
ORDER BY (user_id, event_date)
);
物化历史数据:
ALTER TABLE analytics.events_local
MATERIALIZE PROJECTION proj_user;
查询可以按 user_id 更有效地跳过 granule。投影数据与主表同生共死,TTL、副本和分区仍跟随表结构。
14.3 聚合投影
ALTER TABLE analytics.events_local
ADD PROJECTION proj_city_daily
(
SELECT
event_date,
city_id,
event_type,
count(),
sum(amount)
GROUP BY event_date, city_id, event_type
);
适合固定维度汇总:
SELECT
event_date,
city_id,
count(),
sum(amount)
FROM analytics.events_local
WHERE event_date = '2026-08-25'
GROUP BY event_date, city_id;
当查询表达式与投影兼容时,优化器可以使用聚合投影代替扫描明细。
14.4 使用条件
Projection 不是缓存,而是额外物理数据。使用前要确认:
- 查询频率足够高;
- 扫描收益明显;
- 写入可承受额外成本;
- 磁盘可承受额外空间;
- 表达式与投影兼容;
- 当前版本优化行为已验证。
14.5 与物化视图对比
| 维度 | Projection | Materialized View |
|---|---|---|
| 归属 | 表内部 | 独立数据库对象 |
| 选择方式 | 优化器选择 | 写入目标表 |
| 灵活性 | 受投影表达式限制 | SQL 更灵活 |
| 生命周期 | 随主表 | 独立管理 |
| 适用 | 换排序、固定聚合 | 复杂转换、分发 |
| 数据边界 | 与主表一致 | 需手动处理回填 |
简单排序变化和固定聚合优先考虑 Projection;复杂清洗、多目标分发、跨表加工优先物化视图。
14.6 管理操作
查看:
SELECT database, table, name, query
FROM system.projections
WHERE table = 'events_local';
删除:
ALTER TABLE analytics.events_local
DROP PROJECTION proj_user;
清除数据但保留定义:
ALTER TABLE analytics.events_local
CLEAR PROJECTION proj_user;
重新物化:
ALTER TABLE analytics.events_local
MATERIALIZE PROJECTION proj_user;
14.7 验证是否命中
查看执行计划:
EXPLAIN
SELECT count(), sum(amount)
FROM analytics.events_local
WHERE event_date = today()
GROUP BY city_id;
再查看查询日志:
SELECT query, read_rows, read_bytes, query_duration_ms
FROM system.query_log
WHERE query_id = 'target-id';
如果查询读取了不同列、不同过滤条件或聚合粒度,优化器可能仍回退到原始数据。
14.8 版本差异
Projection 的支持范围、语法、优化器行为和系统表字段在不同版本间存在差异。生产使用前应在目标版本测试,并保留无投影执行基线、写入吞吐变化、磁盘增长和回滚方式。
14.9 常见问题
| 问题 | 原因 |
|---|---|
| 查询没有命中 | 表达式不兼容 |
| 写入变慢 | 投影额外计算和落盘 |
| 磁盘增长 | 多份物理数据 |
| 历史数据无效 | 未物化 |
| 合并变慢 | 需要维护投影 |
| 优化不稳定 | 版本或查询形态变化 |
本章小结
Projection 适合为同一张表补充不同排序或固定聚合视图,由优化器自动选择。它比物化视图更内聚,但灵活性和版本行为要谨慎评估。使用前用扫描量、写入吞吐和磁盘成本做完整对比。
思考题
- 普通投影和聚合投影分别解决什么问题?
- Projection 和物化视图如何选择?
- 为什么 Projection 会增加写入成本?
- 如何确认查询命中投影?
- 投影上线前需要哪些回滚准备?