目录
一、ClickHouse
主键
表引擎
(1)MergeTree
(2) AggregatingMergeTree
(3)ReplacingMergeTree
(4)SummingMergeTree
数据副本
压缩
低基
二、Clickhouse 分布式表介绍和创建、插入和查询数据,以及解决遇到的问题
ClickHouse由俄罗斯最大的搜索引擎公司Yandex研发,设计目标是支持Yandex.Metrica(世界第二大Web分析平台)生成用户分析报表等核心功能。ClickHouse是一个数据库管理系统(DBMS),有数据库、表、视图、DDL、DML等概念,并提供了较为完整的SQL支持。其核心特性有如下几点:
ClickHouse支持的主键并不是传统意义下关系型数据库的主键。传统的主键要求每条表记录都有唯一的键值,通过查询主键可以唯一地查询到一条表记录。而在ClickHouse中,主键定义了记录在存储中排序的顺序,允许重复,所以称之为排序键似乎更加合理。事实上在ClickHouse里的主键定义通过ORDER BY声明,仅在个别场景中允许和排序键不一致(但必须是排序键的前缀)。
ClickHouse中的主键,和其他数据库不太一样,它只提供了数据的一级索引,但是却不是唯一约束。这就意味着是可以存在相同primary key的数据的。
一般情况下,ClickHouse表的主键(Primary Key)和排序键(Order By Key)相同,但是采用了汇总合并树引擎(SummingMergeTree)的表可以单独指定主键。把一些不需要排序或者索引功能的维度字段从主键里排除出去,可以减小主键的大小(主键运行时需要全部加载到内存中),提高查询效率。
Clickhouse 中最强大的表引擎当属
MergeTree
引擎及*MergeTree
中的其他分支引擎。
ClickHouse的存储引擎的核心是合并树(MergeTree),以此为基础衍生出汇总合并树(SummingMergeTree),聚合合并树(AggregationMergeTree),版本折叠树(VersionCollapsingTree)等常用的表引擎。另外上述所有的合并树引擎都有复制功能(ReplicatedXXXMergeTree)的对应版本。
数据是由多组part文件组成,每一个part的数据是按照主键进行字典序排列。这些数据片段在后台按照一定规则合并。
该引擎继承自 MergeTree,并改变了数据片段的合并逻辑。ClickHouse 会将一个数据片段内所有具有相同主键(准确的说是 排序键)的行,替换为单个存储一系列聚合函数状态的行。
可以使用 AggregatingMergeTree 表来做增量数据统计聚合,包括物化视图的数据聚合。
下面我们看个使用例子:
create table test.test_aggremergetree (
id Int32 comment 'id',
name String comment '名称',
money AggregateFunction(sum, Decimal32(2)) COMMENT '工资',
create_at DateTime comment '创建时间'
) engine = AggregatingMergeTree()
order by id
partition by toYYYYMM(create_at)
primary key id
sample by id
TTL create_at + INTERVAL 1 MONTH DELETE;
插入数据如下: 注意:需要使用INSERT…SELECT语句进行数据插入
insert into table test_aggremergetree select 1,'测试',sumState(toDecimal32(10333,2)),now();
insert into table test_aggremergetree select 1,'测试',sumState(toDecimal32(10,2)),now();
insert into table test_aggremergetree select 1,'测试',sumState(toDecimal32(10,2)),now();
查询数据结果如下:
select id,name,sumMerge(money) from test_aggremergetree group by id,name;
AggregatingMergeTree这个其主要功能其实是做物化视图,数据量太多了 可能针对于好几个条件聚合取sum的功能。
该引擎和 MergeTree 的不同之处在于它会删除排序键值相同的重复项。但数据的去重只会在数据合并期间进行,merge操作是后台进程异步执行。合并会在后台一个不确定的时间进行,因此你无法预先作出计划。
有一些数据可能仍未被处理。尽管你可以调用 OPTIMIZE 语句发起计划外的合并,但请不要依靠它,因为 OPTIMIZE 语句会引发对数据的大量读写。
OPTIMIZE TABLE 操作可以手动触发merge操作,但会引发对大量数据的读和写操作,降低性能。因此,ReplacingMergeTree 适用于在后台清除重复的数据以节省空间,并不保证没有重复的数据出现。
一般这个引擎的使用都需要设置一个时间,为了避免数据没有及时清理,需要取数据的时候按照排序键取最近的时间的那条数据。
CREATE TABLE default.t1 (
`gmt` Date, `id` UInt16,
`name` String,
`ver` UInt16
) ENGINE = ReplacingMergeTree(gmt, name, 8192, ver)
合并的时候,ReplacingMergeTree 从所有具有相同主键的行中选择一行留下:
该引擎继承自 MergeTree。区别在于,当合并 SummingMergeTree 表的数据片段时,ClickHouse 会把所有具有相同主键的行进行汇总,将同一主键的行替换为包含sum后的一行记录,该行包含了被合并的行中具有数值数据类型的列的汇总值。
如果主键的组合方式使得单个键值对应于大量的行,则可以显著的减少存储空间并加快数据查询的速度。
这个引擎和听起来和AggregatingMergeTree差不多,但是使用方面明显不一样。 SummingMergeTree我们来看例子,不需要使用聚合函数。 创建表:
CREATE TABLE test.test_summergetree
(
`id` Int32 COMMENT 'id',
`name` String COMMENT '名称',
`money` AggregateFunction(sum, Decimal32(2)) COMMENT '工资',
`create_at` DateTime COMMENT '创建时间'
)
ENGINE = SummingMergeTree([columns])
PARTITION BY toYYYYMM(create_at)
PRIMARY KEY id
ORDER BY id
SAMPLE BY id
TTL create_at + toIntervalMonth(1)
插入数据:
insert into table test_summergetree select 1,'测试',100,now();
insert into table test_summergetree select 1,'测试',200,now();
insert into table test_summergetree select 1,'测试',400,now();
insert into table test_summergetree select 1,'测试222',400,now();
insert into table test_summergetree select 1,'测试222',600,now();
insert into table test_summergetree select 11,'测试222',600,now();
insert into table test_summergetree select 11,'测试222',800,now();
等了一会之后我们查询数据结果如下:
┌─id─┬─name─┬───money─┬───────────create_at─┐
│ 1 │ 测试 │ 1700.00 │ 2021-03-27 19:44:23 │
└────┴──────┴─────────┴─────────────────────┘
┌─id─┬─name────┬──money─┬───────────create_at─┐
│ 11 │ 测试222 │ 600.00 │ 2021-03-27 19:45:37 │
└────┴─────────┴────────┴─────────────────────┘
┌─id─┬─name────┬──money─┬───────────create_at─┐
│ 11 │ 测试222 │ 800.00 │ 2021-03-27 19:45:42 │
└────┴─────────┴────────┴─────────────────────┘
┌─id─┬─name────┬──money─┬───────────create_at─┐
│ 11 │ 测试222 │ 800.00 │ 2021-03-27 19:45:54 │
└────┴─────────┴────────┴─────────────────────┘
id为1的已经聚合成功了,但是id为11还没有聚合成功。
SummingMergeTree主要是用于主键聚合的计算。
只有 MergeTree 系列里的表可支持副本:只有如下的引擎支持复制表。其实就是在对应的引擎前面加上Replicated即可。(我这里特殊说明一下,之前我们用复制表引擎,买了阿里云的clickhouse,结果插入数据会丢失,问了阿里云的人,他们说单副本不支持复制表引擎,这里可以说其实是他们自己服务搭建的架构有bug,因为这样的问题我们当时查了3天,才查出来这个原因。)
日志引擎系列,这些引擎是为了需要写入许多小数据量(少于一百万行)的表的场景而开发的。 StripeLog Log TinyLog
还有一些特殊引擎 URL:用于管理远程 HTTP/HTTPS 服务器上的数据 Memory:引擎以未压缩的形式将数据存储在 RAM 中 分布式引擎:本身不存储数据, 但可以在多个服务器上进行分布式查询。分布式表其实就是视图,主要是分布式集群用于查询多个节点的数据的。
ClickHouse支持列级别的数据压缩,显著地减少原始数据的存储量,这也是列存储引擎的巨大优势。查询阶段,较小的存储占用也可以减少IO量。对不同列选择一种合适的压缩算法和等级,能把压缩和查询的平衡做到性价比最优。
ClickHouse的所有列默认使用LZ4压缩。除此以外,一般的数据列可以选择更高压缩率的算法如LZ4HC,ZSTD;而对于类似时间序列的单调增长数据可以选择DoubleDelta, Gorilla等特殊压缩算法。LZ4HC和ZSTD等高压缩率的算法还可以自己选择压缩级别。在我们的生产数据集上,ZSTD算法对String类型字段压缩效果较为显著。LZ4HC是LZ4的高压缩比改进版,更适用于非字符串类型。
更高的压缩率意味着更少的存储空间,同时由于降低了查询的IO量,可以间接提升查询性能。不过CPU也不是大风刮来的,数据的插入性能就成了牺牲品。
值得一提的是,对于基数较低的列(即列值多样性低),可以使用LowCardinality来降低原始存储空间(从而降低最终存储空间)。如果在使用压缩算法的情况下对一字符串类型的列使用LowCardinality,还能再缩小25%的空间量。
请移步python Clickhouse 分布式表介绍和创建、插入和查询数据,以及解决遇到的问题_水w的博客-CSDN博客_clickhouse查询分布式表