投影概述
- 在不属于主键的列上执行查询
- 对列进行预聚合,从而同时减少计算和 IO
磁盘占用投影会在内部创建一个新的隐藏表,这意味着会需要更多的 IO 和磁盘空间。
例如,如果投影定义了不同的主键,原始表中的所有数据都会被复制一份。
使用投影
不使用主键进行过滤的示例
ALTER TABLE,可以将投影添加到现有表中:
user_name 进行过滤,即使在原始表中,user_name 没有被定义为 PRIMARY_KEY。
在查询时,ClickHouse 会判断使用 projection 后需要处理的数据量更少,因为数据是按 user_name 排序的。
system.query_log 表。projections 字段中会显示所使用的 projection 名称;如果未使用任何 projection,则该字段为空:
预聚合查询示例
projection_visits_by_user 的表:
user_agent 执行第一个带 GROUP BY 的查询。
由于预聚合不匹配,此查询不会使用该 projection。
GROUP BY 字段中的部分或全部字段:
system.query_log 表,以确认是否使用了投影。
projections 字段会显示所使用的投影名称。
如果未使用任何投影,该字段将为空:
创建和使用投影索引
_part_offset 字段在合并和变更后仍会保留其值,因此对二级索引非常有用。我们可以在查询中利用这一点:
管理投影
ADD PROJECTION
WITH SETTINGS 子句
WITH SETTINGS 用于定义投影级设置,以自定义投影存储数据的方式 (例如 index_granularity 或 index_granularity_bytes) 。
这些设置与 MergeTree 表设置 一一对应,但仅对当前投影生效。
示例:
DROP PROJECTION
MATERIALIZE PROJECTION
partition_name 中的PROJECTION name。
这是通过变更实现的。
CLEAR PROJECTION
ADD、DROP 和 CLEAR 都属于轻量级操作,因为它们只会修改元数据或删除文件。
此外,这些命令支持复制,并通过 ClickHouse Keeper 或 ZooKeeper 同步PROJECTION元数据。
只有使用
*MergeTree 引擎的表 (包括复制变体) 才支持PROJECTION操作。控制投影合并行为
ReplacingMergeTree 表引擎存储。
如果在合并期间从多个输入分片中检测到相同的行,则只会保留最新的行版本 (来自最近插入的分片) ,而所有较旧版本都会被丢弃。
类似地,如果该表使用 AggregatingMergeTree 表引擎存储,则合并操作可能会将输入分片中的相同行 (基于主键值) 折叠为单个行,以更新部分聚合状态。
在 ClickHouse v24.8 之前,投影分片要么会悄然与主数据失去同步,要么某些操作 (如更新和删除) 根本无法执行,因为如果表包含投影,数据库会自动抛出异常。
从 v24.8 开始,新增了一个表级设置 deduplicate_merge_projection_mode,用于控制当前述非平凡后台合并操作发生在原始表分片中时的行为。
删除变更是另一类会删除原始表分片中行的分片合并操作。自 v24.7 起,我们还提供了一个设置,用于控制由轻量级删除触发的删除变更相关行为:lightweight_mutation_projection_mode。
下面是 deduplicate_merge_projection_mode 和 lightweight_mutation_projection_mode 的可能值:
throw(默认) :抛出异常,防止投影分片失去同步。drop:删除受影响的投影表分片。对于受影响的投影分片,查询将回退到原始表分片。rebuild:重建受影响的投影分片,使其与原始表分片中的数据保持一致。
限制
ORDER BY 子句中使用 ALIAS 列。例如:
ALIAS 列不会被物理存储,而是在查询时动态计算,因此在计算排序表达式时,投影部分的写入路径无法使用这些列。
请改用 MATERIALIZED 列,或直接内联表达式: