ClickHouse Projection

前面我们介绍MergeTree引擎的时候,唯独建表语句中的 PROJECTION 定义项没有介绍,在了解完二级索引和物化视图后,本篇文章就来细说一下这个非常重要的功能。

在创建MergeTree表的时候可以定义ORDER BY字段,如果基于ORDER BY字段查询,速度会很快,但是ORDER BY字段是固定的,一旦查询非ORDER BY字段或者不是按照ORDER BY字段顺序查询,效率都会降低。此时,我们可以创建二级索引(跳数索引)或者物化视图等,但是二级索引只是一些粗粒度的索引,例如min/max等,而物化视图数据是独立存储的,无法感知删除操作,还会拖累原表写入性能。针对这种情况,ClickHouse还提供了另外一个新功能——Projection。(Projection是ClickHouse 21.6才有的新特性,使用的时候需要注意版本支持。)

Projection类似物化视图但是是part-level存储,在一张表的分区子目录里面有一个独立的projection数据存储,也就是说它和原表分区在一起,数据是同源的,而且提供了一致性保证。这也就意味着如果原表的数据变了,那么projection也会发生变化。其次,projection的使用是无感的,它更像是原表的一个智能索引,对一张表可以创建很多个projection,在查询时会根据算法去自动匹配。如果能匹配上,就用一个最优的projection提供查询加速,如果没有命中还是查原表。有了这些特性以后,projection比使用物化视图方便非常多。

※注意:带有FINAL修饰符的SELECT语句不支持projection。

projection优化默认是不开启的,有两个配置项需要设置:

  • allow_experimental_projection_optimization:在处理SELECT查询时启用或禁用projection优化,0禁止,1开启,默认是0。
  • force_optimize_projection:当开启projection优化时,启用或禁用在SELECT查询中强制使用projection,0不强制使用,1强制使用,默认是0。

创建projection有两种方法,第一种是在建表的时候定义,第二种是在后期添加:

-- 建表指定
CREATE TABLE table_name 
(
    name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1] [TTL expr1],
    name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2] [TTL expr2],
    ...
    INDEX index_name1 expr1 TYPE type1(...) GRANULARITY value1,
    INDEX index_name2 expr2 TYPE type2(...) GRANULARITY value2,
    ...
    PROJECTION p1 (SELECT WatchID, Title ORDER BY WatchID),
    PROJECTION p2 (SELECT UserID, SearchPhrase, count() GROUP BY UserID, SearchPhrase)
) ENGINE = MergeTree()
ORDER BY ...
PARTITION BY ...;

-- ALTER添加
ALTER TABLE table_name ADD PROJECTION p1
(
    SELECT 
        WatchID, Title
    ORDER BY WatchID
);
ALTER TABLE table_name ADD PROJECTION p2
(
    SELECT 
        UserID, SearchPhrase, count()
    GROUP BY UserID, SearchPhrase
);

再来看一下table_name的底层文件存储结构。
projection目录结构
可以发现在对应的分区目录下,多了一个projection子目录,而且目录中的文件内容和外部原表的数据存储结构非常像,只是没有元数据信息。此时,projection的原理就基本明了了。projection基于定义维护了一份独立的数据存储,但是因为是跟踪原表分区目录存在的,所以不需要保存元数据信息。如果projection的定义语句是ORDER BY,则projection的子目录存储引擎就是MergeTree,如果projection的定义语句是GROUP BY,底层存储引擎变成AggregatingMergeTree,所有聚合函数都转换为AggregateFunction。当在查询中,能匹配到的projection时,就会使用部分预处理好的数据直接返回,这也正是projection加速的本质。例如可以定义一个包含GROUP BY的聚合projection,对于明细数据可以直接查原表,聚合数据通过projection获得。

目前projection不支持跨表操作,所以对于有跨表的预聚合的场景,例如join,还是要利用物化视图。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值