1.概述

转载:ClickHouse王炸功能来袭,性能轻松提升40倍

各位,今年 ClickHouse 最王炸的功能来啦,没错,就是期待已久的 Projection (投影) 功能。ClickHouse 现在的功能已经非常丰富强大了,但是社区用现实告诉我们,还可以进一步做的更好:)

不知道你有没有碰到过这些情况:

MergeTree 只支持一种排序规则

建表的时候,Order By 同时决定了主键稀疏索引和数据的排序,假设 :

Order BY A,B,C

那么通常过滤查询 Where A 会很快,但是 Where C 会慢一些。

物化视图不够智能

针对固定的查询主题,我们会基于一张底表构建许多物化视图,以帮助更进一步提升查询性能、提升QPS、降低资源开销。

物化视图虽然效果显著,但是却不够智能。物化视图本质上一张独立的表,通过原表的触发器,实时的向视图表写入数据。

既然物化视图也是独立的表,那么自然就会存在与原表数据一致性的问题。如果物化视图很多,维护起来也是一个问题。

Projection 功能的出现,完美解决了上述的问题。Projection 的概念出自 《C-Store: A Column-oriented DBMS》这篇论文,作者是2015年图灵奖获得者、Vertica 之父,Mike Stonebraker。

Projection 意指一组列的组合,可以按照与原表不同的排序存储,并且支持聚合函数的查询。

来自快手的 Amos Bird(郑天祺) 借鉴了这个思想,在 ClickHouse 中实现了 Projection 的功能,并贡献到社区。

ClickHouse Projection 可以看做是一种更加智能的物化视图,它有如下特点:

  • part-level 存储 : 相比普通物化视图是一张独立的表,Projection 物化的数据就保存在原表的分区目录中,支持明细数据的普通Projection 和 预聚合Projection

  • 无感使用,自动命中 可以对一张 MergeTree 创建多个 Projection ,当执行 Select 语句的时候,能根据查询范围,自动匹配最优的 Projection 提供查询加速。如果没有命中 Projection , 就直接查询底表。

  • 数据同源、同生共死 因为物化的数据保存在原表的分区,所以数据的更新、合并都是同源的,也就不会出现不一致的情况了

这么干讲可能还比较抽象,直接来看用例吧,这里直接使用官方的测试数据集 hits_100m_obfuscated,这张表有 1亿 数据:

SELECT count(*)
FROM hits_100m_obfuscatedQuery id: 813ba930-d299-47d8-9ac3-6d7dbde075b1┌───count()─┐
│ 100000000 │
└───────────┘1 rows in set. Elapsed: 0.004 sec.

Order By 是:

ENGINE = MergeTree
PARTITION BY toYYYYMM(EventDate)
ORDER BY (CounterID, EventDate, intHash32(UserID), EventTime)

在没有 Projection 的时候,查询非主键 WatchID:

SELECT WatchID
FROM hits_100m_obfuscated
WHERE WatchID = 5814563137538961516Query id: 20110b52-cac0-43b7-baf6-1931b94864a6┌─────────────WatchID─┐
│ 5814563137538961516 │
└─────────────────────┘1 rows in set. Elapsed: 0.262 sec. Processed 100.00 million rows, 800.00 MB (380.95 million rows/s., 3.05 GB/s.)

结果全表扫描了 800MB 共 1亿行数据。

现在创建一个 Projection ,为特定的 Where 字段加速,按查询的需求生成有别于主键的,另外一种排序规则:


ALTER TABLE hits_100m_obfuscated ADD PROJECTION p1
( SELECT WatchID,TitleORDER BY WatchID
)

注意,只有在创建 PROJECTION 之后,再被写入的数据,才会自动物化。

对于历史数据,需要手动触发物化,例如现在我们就需要执行:

alter table hits_100m_obfuscated MATERIALIZE PROJECTION p1

MATERIALIZE PROJECTION 是一个异步的 Mutation 操作,可以通过下面的语句查询状态:

SELECTtable,mutation_id,command,is_done
FROM system.mutations AS m
WHERE is_done = 0Query id: 7ddc855a-acb5-4ca9-8c48-ad4f5a7b234e┌─table────────────────┬─mutation_id─────┬─command───────────────────┬─is_done─┐
│ hits_100m_obfuscated │ mutation_99.txt │ MATERIALIZE PROJECTION p1 │       0 │
└──────────────────────┴─────────────────┴───────────────────────────┴─────────┘1 rows in set. Elapsed: 0.005 sec.

这个时候,如果我们去分区目录,你会看到一个 tmp 临时分区,正在物化 PROJECTION 的数据:


等到 p1 PROJECTION 生成好了之后,我们再去看分区目录:


会看到在原有 MergeTree 的分区下,多了一个 p1.proj 的子目录,进入子目录,你会发现和 MergeTree 的存储格式是一样的:


cd /data/default/hits_100m_obfuscated/201307_1_96_4_107/p1.proj
[root@ch9 p1.proj]# ll
total 5187772
-rw-r-----. 1 clickhouse clickhouse        278 Sep  8 23:43 checksums.txt
-rw-r-----. 1 clickhouse clickhouse         69 Sep  8 23:43 columns.txt
-rw-r-----. 1 clickhouse clickhouse          9 Sep  8 23:43 count.txt
-rw-r-----. 1 clickhouse clickhouse         10 Sep  8 23:43 default_compression_codec.txt
-rw-r-----. 1 clickhouse clickhouse      97672 Sep  8 23:43 primary.idx
-rw-r-----. 1 clickhouse clickhouse 4508224709 Sep  8 23:43 Title.bin
-rw-r-----. 1 clickhouse clickhouse     293016 Sep  8 23:43 Title.mrk2
-rw-r-----. 1 clickhouse clickhouse  803340103 Sep  8 23:43 WatchID.bin
-rw-r-----. 1 clickhouse clickhouse     293016 Sep  8 23:43 WatchID.mrk2

当查询命中某个 PROJECTION 的时候,就会直接用分区子目录中的数据,来提供查询。

再有了 p1 PROJECTION 之后,再次执行同样的查询,记得首先要设置参数开启这项功能

SET allow_experimental_projection_optimization = 1;

执行查询:

SELECT WatchID
FROM hits_100m_obfuscated
WHERE WatchID = 5814563137538961516Query id: 38d2aa48-45da-4487-ab80-1cd02ee08ce2┌─────────────WatchID─┐
│ 5814563137538961516 │
└─────────────────────┘1 rows in set. Elapsed: 0.006 sec. Processed 8.19 thousand rows, 65.54 KB (1.41 million rows/s., 11.27 MB/s.)

效果惊人,从 800MB 的 1亿 行全表扫描,缩减到 65KB 的 8k 行扫描,时间也加快了 40 多倍。

除了明细数据的查询,PROJECTION 也支持预聚合,在没有优化的情况下,下面的查询也会全表扫描:


SELECTUserID,SearchPhrase,count()
FROM hits_100m_obfuscated
GROUP BYUserID,SearchPhrase
LIMIT 10Query id: 42c941e0-c15a-4206-9c1b-7350a5a67984┌───────────────UserID─┬─SearchPhrase─────────────────────────────────────────────────┬─count()─┐
│    64240392369242065 │                                                              │       1 │
│  2542641703475366060 │ galaxy s4 activerstovmamasumi x2                             │       3 │
│ 14973463213479722228 │                                                              │      17 │
│  6604743450870066038 │                                                              │       1 │
│   325929602194382277 │ вес гриппи игре aventity of wars 2 в в играть                │       1 │
│  5481644077966220011 │ как леченский рецепты как почему конкая лето москва отдых на │       1 │
│  5965198553492672379 │                                                              │       1 │
│   119657425828985633 │                                                              │       1 │
│  8462750442030450647 │ рулонасточный+статив зомбинет магазин на айресу батл         │       1 │
│  7510587892824469257 │ sia 265 сезон 6 серии                                        │       1 │
└──────────────────────┴──────────────────────────────────────────────────────────────┴─────────┘10 rows in set. Elapsed: 2.190 sec. Processed 100.00 million rows, 2.44 GB (45.66 million rows/s., 1.11 GB/s.)

现在创建另外一个聚合 PROJECTION:

ALTER TABLE hits_100m_obfuscated ADD PROJECTION agg_p2( SELECTUserID, SearchPhrase, count()GROUP BY UserID, SearchPhrase)

由于历史数据已经存在,也要手动触发一下物化:

alter table hits_100m_obfuscated MATERIALIZE PROJECTION agg_p2

物化好了之后,再次执行相同的查询:

SELECTUserID,SearchPhrase,count()
FROM hits_100m_obfuscated
GROUP BYUserID,SearchPhrase
LIMIT 10Query id: 258e556e-ea5b-43f0-980a-997c02abc233┌───────────────UserID─┬─SearchPhrase─────────────────────────────────────────────────┬─count()─┐
│    64240392369242065 │                                                              │       1 │
│  2542641703475366060 │ galaxy s4 activerstovmamasumi x2                             │       3 │
│ 14973463213479722228 │                                                              │      17 │
│  6604743450870066038 │                                                              │       1 │
│   325929602194382277 │ вес гриппи игре aventity of wars 2 в в играть                │       1 │
│  5481644077966220011 │ как леченский рецепты как почему конкая лето москва отдых на │       1 │
│  5965198553492672379 │                                                              │       1 │
│   119657425828985633 │                                                              │       1 │
│  8462750442030450647 │ рулонасточный+статив зомбинет магазин на айресу батл         │       1 │
│  7510587892824469257 │ sia 265 сезон 6 серии                                        │       1 │
└──────────────────────┴──────────────────────────────────────────────────────────────┴─────────┘10 rows in set. Elapsed: 1.847 sec. Processed 24.07 million rows, 1.58 GB (13.04 million rows/s., 856.09 MB/s.)

数据扫描范围减少了四分之三。

现在 ClickHouse 也提供了 PROJECTION 的系统表,可以看到相关的存储信息:


SELECTname,partition,formatReadableSize(bytes_on_disk) AS bytes,formatReadableSize(parent_bytes_on_disk) AS parent_bytes,parent_rows,rows / parent_rows AS ratio
FROM system.projection_partsQuery id: 2887b0e1-b984-4274-862c-0b59c68693c5┌─name───┬─partition─┬─bytes──────┬─parent_bytes─┬─parent_rows─┬──────ratio─┐
│ agg_p2 │ 201307    │ 490.40 MiB │ 14.06 GiB    │   100000000 │ 0.24070565 │
│ p1     │ 201307    │ 4.95 GiB   │ 18.53 GiB    │   100000000 │     1      │
└────────┴───────────┴────────────┴──────────────┴─────────────┴────────────┘

PROJECTION 本质也是在用空间换时间,还是还很划算的。

PROJECTION 也支持删除的 DDL:

ALTER TABLE hits_100m_obfuscated DROP PROJECTION p1ALTER TABLE hits_100m_obfuscated DROP PROJECTION agg_p2

除了通过 ALTER 创建,也能在 CREATE TABLE 的时候创建,例如:

CREATE TABLE xxx
( `event_key` String, `user` UInt32, `dim1` String, PROJECTION p1 ( SELECT groupBitmap(user), count(1) GROUP BY dim1 )
)
ENGINE = MergeTree()
ORDER BY (event_key, user)

通过刚才的例子,你能发现在查询时, PROJECTION 的使用是无感的,ClickHouse 会根据提交的 SQL 语句自动匹配。

那么你肯定会好奇,匹配的规则是什么呢?有这么几条原则:

  1. 设置了 SET allow_experimental_projection_optimization = 1

  2. 返回的数据行小于基表总数

  3. 查询覆盖的分区 part 超过一半

  4. Where 必须是 PROJECTION 定义中 GROUP BY 的子集

  5. GROUP BY 必须是 PROJECTION 定义中 GROUP BY 的子集

  6. SELECT 必须是 PROJECTION 定义中 SELECT 的子集

  7. 匹配多个 PROJECTION 的时候,选取读取 part 最少的

如果你不知道查询是否匹配了 PROJECTION ,有两种方式可以校验:

  1. 使用 explain ,例如:
EXPLAIN
SELECT WatchID
FROM hits_100m_obfuscated
WHERE WatchID = 5814563137538961516Query id: bf008e69-fd68-4928-83f6-a57a2d84e286┌─explain───────────────────────────────────────────────────────────────────┐
│ Expression ((Projection + Before ORDER BY))                               │
│   SettingQuotaAndLimits (Set limits and quota after reading from storage) │
│     ReadFromStorage (MergeTree(with 0 projection p1))                     │
└───────────────────────────────────────────────────────────────────────────┘

看到 MergeTree(with 0 projection p1) 就代表这条 SQL 查询会命中 PROJECTION

  1. 查看执行日志:
 (SelectExecutor): Choose normal projection p3(SelectExecutor): projection required columns: dim1, dim3, event_time, dim2, event_key, user(SelectExecutor): Key condition: (column 0 in ['dim12', 'dim12'])

看到 Choose xxx projection 就代表这条 SQL 查询已经命中 PROJECTION

利用 PROJECTION ,我们只需面对一张底表查询就行了,既拥有原来物化视图的性能,又免去了维护成本和数据一致性的问题,简直无敌啊。


好了,今天的分享就到这里,再有了 PROJECTION 之后,可以说 ClickHouse 更加的如虎添翼了。在原有的一些场景下,我们可以告别 ETL和物化视图了。

作者 朱凯

关于作者:朱凯,ClickHouse贡献者之一,ClickHouse布道者,资深架构师,腾讯云最具价值专家TVP,开源爱好者,Apache DolphinScheduler Committer,《ClickHouse原理解析与应用实战》作者。

【clickhouse】clickhouse强大智能的 Projection (投影) 功能相关推荐

  1. 智能数字橱窗投影广告——让橱窗玻璃变身数字高清大屏

    橱窗广告效果图 城市遍布商家门店--门店就是商家生意的脸面.对外经营的窗口.大多数商家都会精心设计自己的门店招牌.门头,尤其玻璃橱窗.橱窗的展示,让过往的人群能否吸引进店消费是值得精心去策划的.传统的 ...

  2. 西门子变频器G120智能操作面板的功能和特点分享

    西门子变频器G120系列在工业自动化控制领域应用广泛,为用户提供高精度的速度控制或转矩控制.它采用模块化设计,提供了高度的灵活性,便于用户使用,维护,并可以在带电的情况下更换模块.同时它还具有强大的通 ...

  3. CATIA三维工程设计软件 强大曲面设计模块工具功能介绍

    CATIA三维工程设计软件是法国达索公司设计开发的一款三维设计工具,拥有强大的曲面设计功能,为用户提供功能强大的曲面设计三维工业设计软件.CATIA软件,是PLM协同解决方案的一个重要组成部分,不仅支 ...

  4. 华为手表计算机有什么功能,华为智能手表功能大全,华为智能手表有什么功能...

    导语:如今华为发布了几款智能手表,对于这款产品,很多对它感兴趣的机友们很想知道华为智能手表有什么功能,值得入手吗?针对大家提出的问题,下面小编就为大家介绍一下华为智能手表功能. 智能手表现在在科技界是 ...

  5. 李国庆离开当当,广东消委会告长隆,智能校服提供定位功能,全球首个5G火车站来了,这就是今天的大新闻...

    今天是2月21日 农历正月十七 今天下雨 出门忘带雨伞 但是心情还是美丽的 因为我没被淋湿 下面是今天的大新闻 李国庆宣布离开一手创办的当当  (界面新闻)2月20日上午,当当联合创始人李国庆正式宣布 ...

  6. 茶云个人导航系统v1.2源码 带后台+网易云歌单播放功能+腾讯智能在线客服功能

    这是一款好看的个人导航网自带后台,本导航系统由奶茶二次开发而成,后添加各种美化,后台自定义添加导航,背景,源码集成网易云歌单播放和腾讯智能在线客服功能使源码更显一个档次! 温馨提示,如果涉及到授权,源 ...

  7. SF-60/385/4PY智能浪涌保护器 带遥信功能 四川 重庆项目大力推荐应用 带通讯 上防雷系统平台

    SF-40/385/4PY智能电源防雷模块 带通讯对接防雷系统 SF-20/385/4PY智能电源防雷模块 40KA.20KA电源防雷模块产品说明 该产品广泛用于光伏电站.充电站.住宅楼.移动通信基站 ...

  8. 智能座舱域控制器功能自动化测试方案

    1. 背景 智能座舱是当前汽车行业开发设计和差异化竞争的焦点,当前智能座舱控制器多为整合了传统IPK.HMI.HUD.DMS等若干控制器之后的"一机多屏"的复杂系统.在软件架构上, ...

  9. 无人机智能巡检系统及功能介绍

    目前,矿区的日常巡检内容主要包括巡查矿区周边是否存在盗采.滥采.周围地形地貌条件等.矿区的日常巡检是整个矿区管理中十分重要的一个环节,但现阶段的巡检管理方式还存在一些难点.在面临恶劣天气和环境时,人工 ...

最新文章

  1. 读自动驾驶激光雷达物体检测技术(Lidar Obstacle Detection)(2):点云滤波FilterCloud()函数
  2. Android之设置ListView数据显示的动画效果
  3. TENSORFLOW PROCESS FINISHED WITH EXIT CODE -1073741819 (0XC0000005)
  4. 【Python】从文件中读取数据
  5. 哪些CSS是可以被继承的--简单整理
  6. oracle extract()截取时间值函数
  7. DISCUZ 品牌空间恼人的游客评论名称Guest修改记录
  8. 【C++基础学习】C++中union结构
  9. Gulp新手入门教程
  10. Java 使用阿里云短信的API接口
  11. Redis哨兵主从配置(半自动)
  12. 我妈劝我找份稳定的工作
  13. 用户自定义控件(UserControl)用法大全
  14. 汽车维修企业管理【1】
  15. Word插入带打勾图标的方框
  16. 本地计算机无法启动dhcp服务,Windows10无法启用dhcp服务怎么办?
  17. 百度搜索结果页面的参数 搜索框提示次数(rsv_sug1)
  18. 线程控制-客户端获取信息无反应
  19. scsi 教程 linux,SCSI存储详解以及Linux下ISCSI的实现
  20. ezcast 有线版 升级

热门文章

  1. 《王者荣耀》回应故障:3个工作日内补发排位赛星积分丢失
  2. 被薅秃了!元气森林:损失近千万元 将为14.05万下单用户每人寄一箱白桃气泡水...
  3. 网传“杭州市聘罗永浩为形象大使”?官方:为不实信息
  4. SpaceX载人龙飞船将于11月份进行首次环绕国际空间站飞行
  5. 比亚迪宋Plus DM-i值得买嘛?
  6. iQOO Neo5搭载66W超快闪充:30分钟回血!
  7. 爱奇艺纪录片《棒!少年》《从长安到罗马》入选广电总局“2020年优秀国产纪录片集锦”...
  8. 国内旅游业务全面复苏 携程后疫情时代如何深耕旅游市场?
  9. 滴滴派发15亿出行消费券 覆盖快车、优享等多产品
  10. 华为上架自主地图应用Here WeGo 或登录HMS系统成为预装应用