ClickHouse介绍

目录

一、ClickHouse

主键

表引擎

(1)MergeTree

(2) AggregatingMergeTree

(3)ReplacingMergeTree

(4)SummingMergeTree

数据副本

压缩

低基

二、Clickhouse 分布式表介绍和创建、插入和查询数据,以及解决遇到的问题


ClickHouse由俄罗斯最大的搜索引擎公司Yandex研发,设计目标是支持Yandex.Metrica(世界第二大Web分析平台)生成用户分析报表等核心功能。ClickHouse是一个数据库管理系统(DBMS),有数据库、表、视图、DDL、DML等概念,并提供了较为完整的SQL支持。其核心特性有如下几点:

  • 高效的数据存储:通过数据压缩和列式存储,可以达到最高10倍的数据压缩率。
  • 高效的数据查询:通过主键索引、向量化引擎处理、多处理器并发和分布式查询,最大压榨CPU的所有能力,在中小规模的数据量上尤为突出。
  • 灵活的数据定义和接入:通过支持SQL语言、JDBC和关系模型,降低学习和迁移成本,可以和其他现有数据的产品无缝集成。

一、ClickHouse

主键

ClickHouse支持的主键并不是传统意义下关系型数据库的主键。传统的主键要求每条表记录都有唯一的键值,通过查询主键可以唯一地查询到一条表记录。而在ClickHouse中,主键定义了记录在存储中排序的顺序,允许重复,所以称之为排序键似乎更加合理。事实上在ClickHouse里的主键定义通过ORDER BY声明,仅在个别场景中允许和排序键不一致(但必须是排序键的前缀)。

ClickHouse中的主键,和其他数据库不太一样,它只提供了数据的一级索引,但是却不是唯一约束。这就意味着是可以存在相同primary key的数据的。

一般情况下,ClickHouse表的主键(Primary Key)和排序键(Order By Key)相同,但是采用了汇总合并树引擎(SummingMergeTree)的表可以单独指定主键。把一些不需要排序或者索引功能的维度字段从主键里排除出去,可以减小主键的大小(主键运行时需要全部加载到内存中),提高查询效率。

表引擎

Clickhouse 中最强大的表引擎当属 MergeTree引擎及*MergeTree中的其他分支引擎。

ClickHouse的存储引擎的核心是合并树(MergeTree),以此为基础衍生出汇总合并树(SummingMergeTree),聚合合并树(AggregationMergeTree),版本折叠树(VersionCollapsingTree)等常用的表引擎。另外上述所有的合并树引擎都有复制功能(ReplicatedXXXMergeTree)的对应版本。

(1)MergeTree

数据是由多组part文件组成,每一个part的数据是按照主键进行字典序排列。这些数据片段在后台按照一定规则合并。

  • ENGINE:表的引擎类型,MergeTree要求有一个日期字段,还有主键
  • PARTITION BY — 分区键
  • ORDER BY — 排序键
  • PRIMARY KEY — 主键,默认情况下主键跟排序键(由 ORDER BY 子句指定)相同
  • SAMPLE BY — 用于抽样的表达式,如果要用抽样表达式,主键中必须包含这个表达式。
  • SETTINGS — 影响 MergeTree 性能的额外参数 index_granularity — 索引粒度 use_minimalistic_part_header_in_zookeeper — 数据片段头在 ZooKeeper 中的存储方式 min_merge_bytes_to_use_direct_io — 使用直接 I/O 来操作磁盘的合并操作时要求的最小数据量,默认10G。

(2) AggregatingMergeTree

该引擎继承自 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;
 
  • AggregatingMergeTree 是在 MergeTree 基础之上,针对聚合函数结果,作增量计算优化的一个设计。
  • 不能使用普通的 INSERT 去添加数据,
    • 一是可以用 INSERT SELECT 来插入数据,
    • 二是可以创建一个物化视图,通过物化视图导入数据。

插入数据如下: 注意:需要使用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的功能。

(3)ReplacingMergeTree

该引擎和 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 从所有具有相同主键的行中选择一行留下:

  • 如果 ver 列未指定,选择最后一条。
  • 如果 ver 列已指定,选择 ver 值最大的版本。

(4)SummingMergeTree

该引擎继承自 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)
 
  • 如果没有指定 [columns],ClickHouse 会把除主键外的其他列都进行汇总。
  • 如果用于汇总的所有列中的值均为0,则该行会被删除。
  • 按片段合并数据,会出现不同数据片段中包含具有相同主键的行。

插入数据:

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天,才查出来这个原因。)

  • ReplicatedMergeTree
  • ReplicatedSummingMergeTree
  • ReplicatedReplacingMergeTree
  • ReplicatedAggregatingMergeTree
  • ReplicatedCollapsingMergeTree
  • ReplicatedVersionedCollapsingMergetree
  • ReplicatedGraphiteMergeTree

日志引擎系列,这些引擎是为了需要写入许多小数据量(少于一百万行)的表的场景而开发的。 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%的空间量。

二、Clickhouse 分布式表介绍和创建、插入和查询数据,以及解决遇到的问题

请移步python Clickhouse 分布式表介绍和创建、插入和查询数据,以及解决遇到的问题_水w的博客-CSDN博客_clickhouse查询分布式表

你可能感兴趣的:(#,数据库,java,开发语言)