ClickHouse(13)ClickHouse合并树MergeTree家族表引擎之CollapsingMergeTree详细解析
该引擎继承于MergeTree,并在数据块合并算法中添加了折叠行的逻辑。CollapsingMergeTree会异步的删除(折叠)这些除了特定列Sign有1和-1的值以外,其余所有字段的值都相等的成对的行。没有成对的行会被保留。因此,该引擎可以显著的降低存储量并提高SELECT查询效率。
简单来说就是,clickhouse会自动的合并有效和无效的数据,减少数据存储,并减少update所产生的性能消耗。具体的逻辑,下面介绍。
建表
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [DEFAULT|MATERIALIZED|ALIAS expr1],
name2 [type2] [DEFAULT|MATERIALIZED|ALIAS expr2],
...
) ENGINE = CollapsingMergeTree(sign)
[PARTITION BY expr]
[ORDER BY expr]
[SAMPLE BY expr]
[SETTINGS name=value, ...]
sign — 类型列的名称:1是«状态»行,也就是最后的有效行,-1是«取消»行,也就是无效行。列数据类型 — Int8。
创建CollapsingMergeTree表时,需要与创建 MergeTree 表时相同的子句。
折叠
数据
考虑你需要为某个对象保存不断变化的数据的情景。似乎为一个对象保存一行记录并在其发生任何变化时更新记录是合乎逻辑的,但是更新操作对DBMS来说是昂贵且缓慢的,因为它需要重写存储中的数据。如果你需要快速的写入数据,则更新操作是不可接受的,但是你可以按下面的描述顺序地更新一个对象的变化。
在写入行的时候使用特定的列Sign。如果Sign=1则表示这一行是对象的状态,我们称之为«状态»行。如果Sign=-1则表示是对具有相同属性的状态行的取消,我们称之为«取消»行。
例如,我们想要计算用户在某个站点访问的页面页面数以及他们在那里停留的时间。在某个时候,我们将用户的活动状态写入下面这样的行。
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
一段时间后,我们写入下面的两行来记录用户活动的变化。
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ -1 │
│ 4324182021466249494 │ 6 │ 185 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
第一行取消了这个对象(用户)的状态。它需要复制被取消的状态行的所有除了Sign的属性。
第二行包含了当前的状态。因为我们只需要用户活动的最后状态,这些行可以在折叠对象的失效(老的)状态的时候被删除。CollapsingMergeTree会在合并数据片段的时候做这件事。
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ 1 │
│ 4324182021466249494 │ 5 │ 146 │ -1 │
└─────────────────────┴───────────┴──────────┴──────┘
这种方法的特殊属性
- 写入的程序应该记住对象的状态从而可以取消它。«取消»字符串应该是«状态»字符串的复制,除了相反的Sign。它增加了存储的初始数据的大小,但使得写入数据更快速。
- 由于写入的负载,列中长的增长阵列会降低引擎的效率。数据越简单,效率越高。
- SELECT的结果很大程度取决于对象变更历史的一致性。在准备插入数据时要准确。在不一致的数据中会得到不可预料的结果,例如,像会话深度这种非负指标的负值。
算法
当ClickHouse合并数据片段时,每组具有相同主键的连续行被减少到不超过两行,一行Sign=1(«状态»行),另一行Sign=-1(«取消»行),换句话说,数据项被折叠了。
对每个结果的数据部分ClickHouse保存的算法:
- 如果«取消»和«状态»行数量相同,并且最后一行«状态»行,保留第一个«取消»和最后一个«状态»行。
- 如果«状态»行比«取消»行多一个或一个以上,保留最后一个«状态»行。
- 如果«取消»行比«状态»行多一个或一个以上,保留第一个«取消»行。
- 没有行,在其他所有情况下。合并会继续,但ClickHouse会把此情况视为逻辑错误并将其记录在服务日志中。这个错误会在相同的数据被插入超过一次时出现。
因此,折叠不应该改变统计数据的结果。变化逐渐地被折叠,因此最终几乎每个对象都只剩下了最后的状态。
Sign是必须的因为合并算法不保证所有有相同主键的行都会在同一个结果数据片段中,甚至是在同一台物理服务器上。ClickHouse用多线程来处理SELECT请求,所以它不能预测结果中行的顺序。如果要从CollapsingMergeTree表中获取完全«折叠»后的数据,则需要聚合。
要完成折叠,请使用GROUP BY子句和用于处理符号的聚合函数编写请求。例如,要计算数量,使用sum(Sign)而不是 count()。要计算某物的总和,使用sum(Sign * x)而不是sum(x),并添加HAVING sum(Sign) > 0子句。
聚合体count,sum和avg可以用这种方式计算。如果一个对象至少有一个未被折叠的状态,则可以计算uniq聚合。min和 max聚合无法计算,因为CollaspingMergeTree不会保存折叠状态的值的历史记录。
如果你需要在不进行聚合的情况下获取数据(例如,要检查是否存在最新值与特定条件匹配的行),你可以在 FROM 从句中使用 FINAL 修饰符。这种方法显然是更低效的。
# 示例:
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ 1 │
│ 4324182021466249494 │ 5 │ 146 │ -1 │
│ 4324182021466249494 │ 6 │ 185 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
# 建表:
CREATE TABLE UAct
(
UserID UInt64,
PageViews UInt8,
Duration UInt8,
Sign Int8
)
ENGINE = CollapsingMergeTree(Sign)
ORDER BY UserID
# 插入数据:
INSERT INTO UAct VALUES (4324182021466249494, 5, 146, 1)
INSERT INTO UAct VALUES (4324182021466249494, 5, 146, -1),(4324182021466249494, 6, 185, 1)
#我们使用两次INSERT请求来创建两个不同的数据片段。如果我们使用一个请求插入数据,ClickHouse只会创建一个数据片段且不会执行任何合并操作。
#获取数据:
SELECT * FROM UAct
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ -1 │
│ 4324182021466249494 │ 6 │ 185 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 5 │ 146 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
#我们看到了什么,哪里有折叠?
#通过两个 INSERT 请求,我们创建了两个数据片段。
#SELECT请求在两个线程中被执行,我们得到了随机顺序的行。
#没有发生折叠是因为还没有合并数据片段。
#ClickHouse 在一个我们无法预料的未知时刻合并数据片段。
#因此我们需要聚合:
SELECT
UserID,
sum(PageViews * Sign) AS PageViews,
sum(Duration * Sign) AS Duration
FROM UAct
GROUP BY UserID
HAVING sum(Sign) > 0
┌──────────────UserID─┬─PageViews─┬─Duration─┐
│ 4324182021466249494 │ 6 │ 185 │
└─────────────────────┴───────────┴──────────┘
# 如果我们不需要聚合并想要强制进行折叠,我们可以在 FROM 从句中使用 FINAL 修饰语。
SELECT * FROM UAct FINAL
┌──────────────UserID─┬─PageViews─┬─Duration─┬─Sign─┐
│ 4324182021466249494 │ 6 │ 185 │ 1 │
└─────────────────────┴───────────┴──────────┴──────┘
# 这种查询数据的方法是非常低效的。不要在大表中使用它。
资料分享
参考文章
- ClickHouse(01)什么是ClickHouse,ClickHouse适用于什么场景
- ClickHouse(02)ClickHouse架构设计介绍概述与ClickHouse数据分片设计
- ClickHouse(03)ClickHouse怎么安装和部署
- ClickHouse(04)如何搭建ClickHouse集群
- ClickHouse(05)ClickHouse数据类型详解
- ClickHouse(06)ClickHouse建表语句DDL详细解析
- ClickHouse(07)ClickHouse数据库引擎解析
- ClickHouse(08)ClickHouse表引擎概况
- ClickHouse(09)ClickHouse合并树MergeTree家族表引擎之MergeTree详细解析
- ClickHouse(10)ClickHouse合并树MergeTree家族表引擎之ReplacingMergeTree详细解析
- ClickHouse(11)ClickHouse合并树MergeTree家族表引擎之SummingMergeTree详细解析
ClickHouse(13)ClickHouse合并树MergeTree家族表引擎之CollapsingMergeTree详细解析的更多相关文章
- ClickHouse(10)ClickHouse合并树MergeTree家族表引擎之ReplacingMergeTree详细解析
目录 建表语法 数据处理策略 资料分享 参考文章 MergeTree拥有主键,但是它的主键却没有唯一键的约束.这意味着即便多行数据的主键相同,它们还是能够被正常写入.在某些使用场合,用户并不希望数据表 ...
- ClickHouse(11)ClickHouse合并树MergeTree家族表引擎之SummingMergeTree详细解析
目录 建表语法 数据处理 汇总的通用规则 AggregateFunction 列中的汇总 嵌套结构数据的处理 资料分享 参考文章 SummingMergeTree引擎继承自MergeTree.区别在于 ...
- ClickHouse(12)ClickHouse合并树MergeTree家族表引擎之AggregatingMergeTree详细解析
目录 建表语法 查询和插入数据 数据处理逻辑 ClickHouse相关资料分享 AggregatingMergeTree引擎继承自 MergeTree,并改变了数据片段的合并逻辑.ClickHouse ...
- Clickhouse表引擎之MergeTree
1.概述 在Clickhouse中有多种表引擎,不同的表引擎拥有不同的功能,它直接决定了数据如何读写.是否能够并发读写.是否支持索引.数据是否可备份等等.本篇博客笔者将为大家介绍Clickhouse中 ...
- UniqueMergeTree:支持实时更新删除的 ClickHouse 表引擎
UniqueMergeTree 开发的业务背景 首先,我们看一下哪些场景需要用到实时更新. 我们总结了三类场景: 第一类是业务需要对它的交易类数据进行实时分析,需要把数据流同步到 ClickHouse ...
- Clickhouse表引擎探究-ReplacingMergeTree
作者:耿宏宇 1 表引擎简述 1.1 官方描述 MergeTree 系列的引擎被设计用于插入极大量的数据到一张表当中.数据可以以数据片段的形式一个接着一个的快速写入,数据片段在后台按照一定的规则进行合 ...
- ClickHouse入门:表引擎-HDFS
前言插件及服务器版本服务器:ubuntu 16.04Hadoop:2.6ClickHouse:20.9.3.45 文章目录 简介 引擎配置 HDFS表引擎的两种使用形式 引用 简介 ClickHous ...
- ClickHouse(02)ClickHouse架构设计介绍概述与ClickHouse数据分片设计
ClickHouse核心架构设计是怎么样的?ClickHouse核心架构模块分为两个部分:ClickHouse执行过程架构和ClickHouse数据存储架构,下面分别详细介绍. ClickHouse执 ...
- 【大数据面试】ClickHouse:介绍、特点、数据类型、引擎、操作、副本、分片
1.介绍 开源的列式存储数据库(DBMS),由C++编写,用于在线分析处理查询(OLAP) 可以通过SQL查询实时生成分析数据报告 解释: DBMS:数据库管理系统 常见的列式存储数据库:Hbase. ...
- EXCEL 如何将多个工作表或工作簿合并到一个工作表
在使用Excel 时,我们经常需要将多个工作表或工作簿合并到一个工作表中,这样我们就能快速地对数据进行分析和统计.对于一般用户而言,除了复制每个工作表后再粘贴,没有其他什么方法了.如果只是合并少数几个 ...
随机推荐
- ChatGPT 可以联网了!浏览器插件下载
Twitter 用户 An Qu 开发了一款新的 Chrome 插件帮助 ChatGPT 上网,安装插件以后 ChatGPT 就可以联!网!了! 简单来说开启插件后,他可以从网上搜索信息,并且根据用户 ...
- Linux通过脚本实现多台主机统一部署
该脚本分成三部分,一部分是获取信息的脚本:getInfo.sh 一个是main脚本:main.sh.一个是ssh连接主机脚本:sshing.sh main.sh #是否检查主机是否存活host_che ...
- DC-9靶场练习
Vulnhub靶场-DC-9 准备工作 kali和靶机都选择NAT模式(kali与靶机同网段) 下载链接:https://download.vulnhub.com/dc/DC-9.zip 一.主机发现 ...
- 你不知道的Map家族中的那些冷门容器
概述 本篇文章主要讲解下Map家族中3个相对冷门的容器,分别是WeakHashMap.EnumMap.IdentityHashMap, 想必大家在平时的工作中也很少用到,或者压根不知道他们的特性以及适 ...
- [python]《Python编程快速上手:让繁琐工作自动化》学习笔记3
1. 组织文件笔记(第9章)(代码下载) 1.1 文件与文件路径 通过import shutil调用shutil模块操作目录,shutil模块能够在Python 程序中实现文件复制.移动.改名和删除: ...
- 失配树学习笔记 | P5829 【模板】失配树
简介 失配树(简称 Fail 树),是基于 KMP 的算法,可以高效的解决复杂的字符串前缀后缀关系问题. 前置知识: KMP 算法(求失配数组) 最近公共祖先(LCA) 希望大家看完这篇文章后可以理解 ...
- P3934 [Ynoi2016] 炸脖龙 I
题面 给一个长为 \(n\) 的序列,\(m\) 次操作,每次操作: 1.区间 \([l,r]\) 加 \(x\) 2.对于区间 \([l,r]\),查询: \[a[l]^{a[l+1]^{a[l+2 ...
- 数字IC设计流程
数字IC设计流程 简单介绍数字IC设计流程
- 【Android】Android 源码方式使用 opencv 库文件
使用方法 opencv 官方的 SDK 已经有编译好的 so 库,我们可以直接使用,因此我们只需要将平台架构对应的 so 库文件以及头文件提取出来,使用 Android.mk 进行预安装,然后在需要使 ...
- Linux环境下:程序的链接, 装载和库[静态链接]
看以下例子 main.c extern int x; int main() { int y = 100; swap(&x,&y); return 0; } int x = 1; voi ...