投影
投影会以一种优化查询执行的格式存储数据,在以下场景中非常有用:
- 在不属于主键的列上运行查询
- 对列进行预聚合,从而同时减少计算和 IO
你可以为一张表定义一个或多个投影。在查询分析阶段,ClickHouse 会在不修改用户所提供查询的前提下,自动选择需要扫描数据量最少的投影。
投影会在内部创建一个新的隐藏表,这意味着需要更多的 IO 和磁盘空间。 例如,如果投影定义了不同的主键,则来自原始表的所有数据都会被复制一份。
你可以在此页面中查看更多关于投影内部工作机制的技术细节。
未使用主键的过滤示例
创建表:
使用 ALTER TABLE,我们可以向现有表添加该 Projection:
写入数据:
该 Projection 使我们即使在原始表中未将 user_name 定义为 PRIMARY_KEY,也能快速按 user_name 进行过滤。
在查询时,ClickHouse 会判断如果使用该 Projection,可以处理更少的数据,因为数据是按 user_name 排序的。
要验证某个查询是否使用了投影,我们可以查看 system.query_log 表。在 projections 字段中,会显示所使用的投影名称;如果未使用任何投影,该字段则为空:
预聚合查询示例
创建包含 Projection 的表:
插入数据:
我们将基于字段 user_agent 执行第一个 GROUP BY 查询;由于预聚合条件不匹配,该查询不会使用已定义的投影。
要使用该投影时,我们可以执行查询,从预聚合字段和 GROUP BY 字段中选择部分或全部列。
如前所述,我们可以查看 system.query_log 表。在 projections 字段中,可以看到所使用的投影名称;如果未使用投影,该字段则为空。
带有 _part_offset 字段的常规投影
创建一个带有常规投影并使用 _part_offset 字段的表:
插入一些示例数据:
将 _part_offset 用作二级索引
_part_offset 字段在合并和变更操作过程中会保留其值,因此非常适合作为二级索引使用。我们可以在查询中加以利用:
投影操作
可以执行以下关于投影的操作:
ADD PROJECTION
ALTER TABLE [db.]name [ON CLUSTER cluster] ADD PROJECTION [IF NOT EXISTS] name ( SELECT <COLUMN LIST EXPR> [GROUP BY] [ORDER BY] ) - 在表的元数据中添加投影定义。
DROP PROJECTION
ALTER TABLE [db.]name [ON CLUSTER cluster] DROP PROJECTION [IF EXISTS] name - 从表的元数据中移除投影描述,并从磁盘中删除投影文件。以变更的形式实现。
MATERIALIZE PROJECTION
ALTER TABLE [db.]table [ON CLUSTER cluster] MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name] —— 此查询会在分区 partition_name 中重建投影 name。其实现方式为一次变更操作。
CLEAR PROJECTION
ALTER TABLE [db.]table [ON CLUSTER cluster] CLEAR PROJECTION [IF EXISTS] name [IN PARTITION partition_name] - 在不删除其定义的情况下,从磁盘中删除投影文件。其实现方式为一种变更。
命令 ADD、DROP 和 CLEAR 在某种意义上可以认为是轻量级的,因为它们只会更改元数据或删除文件。
此外,这些操作是可复制的,会通过 ClickHouse Keeper 或 ZooKeeper 同步投影元数据。
只有使用 *MergeTree 引擎(包括复制引擎变体)的表才支持对投影的操作。