MergeTree 家族表上,而无需实际构建或存储它们。它们仅存在于当前会话中,可通过 EXPLAIN WHATIF 列出。
EXPLAIN WHATIF 会对普通 (排序) 假设 PROJECTION 进行估算:对于某个查询,读取该 PROJECTION 会涉及多少标记和行,以及优化器是否会选择它而不是基表。并非所有 PROJECTION 都会被估算:聚合 PROJECTION 和带有 WHERE 子句的 PROJECTION 就属于这种情况,未被估算的候选 PROJECTION 在列出时会附带原因。完整列表请参阅 EXPLAIN WHATIF。当前会话中的假设 PROJECTION 也可以在 system.hypothetical_projections 中查看。
CREATE HYPOTHETICAL PROJECTION
ALTER TABLE ... ADD PROJECTION 相同,定义的校验方式也完全一致,因此在这里被拒绝的 PROJECTION 同样不可能被 materialized。此过程不会构建或写入任何内容——仅在当前会话中存储该描述。
name— PROJECTION 名称;在本会话中必须在(database, table)范围内唯一,且不得与表上已有的真实 PROJECTION 重名。- body 支持与真实 PROJECTION 相同的各种形式:使用
ORDER BY的重排序 PROJECTION、使用GROUP BY的聚合 PROJECTION、使用WHERE的过滤 PROJECTION,或 PROJECTION 索引形式INDEX <expression> TYPE <projection_index_type>。 WITH SETTINGS (...)会被接受并保留;这些设置可在system.hypothetical_projections中查看。
Atomic 数据库中的 MergeTree 家族表 (即必须具有 UUID) ,因为会话存储以表的 UUID 作为 entries 的键。真实 ADD PROJECTION 施加的各项限制在这里同样适用:带有 UNIQUE KEY 的表、在 deduplicate_merge_projection_mode = throw 下非 Ordinary 的 merging 模式、旧语法的 MergeTree 以及不可变磁盘均会被拒绝。
示例
DROP HYPOTHETICAL PROJECTION
DROP ALL HYPOTHETICAL PROJECTIONS
DROP ALL HYPOTHETICAL INDEXES 的作用则相反。
作用域与生命周期
- 假设投影仅存在于当前会话中——对其他会话不可见,并在会话结束时被丢弃。
- 定义或删除假设投影不会真正构建 PROJECTION,也绝不会影响针对该表的普通查询。
- 可通过
system.hypothetical_projections查看当前会话的假设投影。
所需特权
CREATE HYPOTHETICAL PROJECTION 需要该表上的 ALTER ADD PROJECTION 特权——与真实的 ALTER TABLE ... ADD PROJECTION 所需特权相同——因为它会根据表的列校验该定义。EXPLAIN WHATIF 需要 PROJECTION 所涉及列上的列级 SELECT 特权才能对其进行估算,这与它对 CREATE HYPOTHETICAL INDEX 的现有要求一致。
DROP HYPOTHETICAL PROJECTION 需要相同的特权,从而确保在删除语句中指定某个表时,不会泄露该表是否存在或是否符合条件;此外,EXPLAIN WHATIF 在根据表校验已存储的定义之前,也会重新检查该特权。DROP ALL HYPOTHETICAL PROJECTIONS 不指定任何表,因此无需任何特权。