1、数据库引擎
1.1 MaterializeMysql【实验性阶段】
物化mysql引擎可以同步mysql表中的所有数据到Clickhouse。在同步过程中,Clickhouse相当于是Mysql的从机读取binlog日志。并且基于这个原理还能同步DDL和DML语句。
1 | CREATE DATABASE databaseName |
1.2 Mysql
mysql引擎相当于一个代理会帮你把语句传给mysql实例运行,然后返回执行结果给你。
1.3 Lazy
这个数据库引擎只适用于*log系列的表引擎。并且仅仅只把数据保存到内存中,过期之后会自动删除。
1.4 Atomic[默认]
该引擎是Clickhouse的默认引擎。能非阻塞的执行RENAME TABLE以及DROP语句。
2、表引擎
2.1 MergeTree
这个是clickhouse最引以为傲的表引擎。他的特点当你插入数据时,clickhouse并不会马上把数据放到一个大数据文件中。而是生成小的数据片段,在后台clickhouse会不定期的执行“合并”数据的操作。这也就是“合并树”命名的由来。其中“合并”操作的具体算法不同又将MergeTree分为了很多子类,他们都基于MergeTree,但是又有不同的特性。
特性:
- 存储的数据都按照主键排序,这样就可以创建稀疏索引,加快查询速度。
- 一个表中的数据还能进一步进行分区,但是要指定分区键
- 支持数据复制,不过这个就要用到ReplicatedMergeTree
- 支持数据采样
数据存储:
表中所有的数据都是按照主键的顺序保存在不同的数据块中。属于不同分区的数据会分配到不同的数据块。在ck的后台中会启动数据合并的操作,但是不会保证同样的主键一定会分配到同样的数据块。如果数据块是以wide
格式存储的,那么每个字段都会是一个物理文件。而用compact
格式保存则整个表中的数据会保存到1个物理文件中。compact
格式适合哪些插入频繁但是量小的表。默认保存为wide
格式。
数据块会逻辑上分为不同的颗粒,每个颗粒是clickhouse能够读取的最小单位。clickhouse会为每一个颗粒做一个标记,标记的内容是该颗粒第一行中的主键值。对于每一列,不管这一列是否包含主键,也会创建这样的标记文件。这个颗粒度的范围是可以通过index_granularity
和index_granularity_bytes
在建表的时候被设置的。
在clickhouse中,主键是允许被重复的,不存在唯一性。
选择主键:
主键的多少并没有做限制,不过主键越多插入速度会越慢,内存消耗也会变高。但是并不会影响查询时(select)的速度。
索引的使用
当一个查询中的条件包含一下条件之一,就可以使用到索引。
- 一个表示与主键/分区键中的部分字段或全部字段相等/不等的比较表达式
- 基于主键/分区键的字段上的
IN
或 固定前缀的LIKE
表达式; - 基于主键/分区键的字段上的某些函数;
- 基于主键/分区键的表达式的逻辑表达式。
跳数索引
四种可用的所用类型:
- minmax
INDEX a ID TYPE minmax GRANULARITY 5
表示记录每5个index_granularity区间数据中的最大值和最小值 - set(max_rows)
INDEX b(ID) TYPE set(100) GRANULARITY 5
表示该索引会记录数据中ID的取值,并且每5个index_granularity最多纪录100条 - ngrambf_v1(n, size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed)
- tokenbf_v1(size_of_bloom_filter_in_bytes, number_of_hash_functions, random_seed)
- bloom_filter(bloom_filter([false_positive])
并发
支持并发访问,插入时不会影响select
。
2.2 Data Replication
以下几个引擎支持数据副本:
- ReplicatedMergeTree
- ReplicatedSummingMergeTree
- ReplicatedReplacingMergeTree
- ReplicatedAggregatingMergeTree
- ReplicatedCollapsingMergeTree
- ReplicatedVersionedCollapsingMergeTree
- ReplicatedGraphiteMergeTree
副本是表级的,部署数据库级别(如mysql)。这意味着在一个数据库中,你可以有支持副本的表,也可以有普通表。insert
和alter
语句都将可以被复制。CREATE
, DROP
, ATTACH
, DETACH
and RENAME
不会被复制。
复制的过程依赖zookeeper集群交换信息,如果zookeeper不可用,那么所有复制表会切换为只读模式。
2.3 SummingMergeTree
集成了MergeTree
的特性,区别在于当插入数据时,SummingMergeTree
会合并主键相同的行,同时非主键字段进行累加汇总(列要是数字类型)。因为汇总这个动作发生在合并的时候,而合并是定期进行的。这意味着你刚刚插入的数据并不会马上汇总,而是以原本的样子存在。这就要求你执行聚合查询时依然要使用sum()
和group by
。
汇总规则:
列中数值类型的值会被汇总。这些列的集合在参数
columns
中被定义。如果用于汇总的所有列中的值均为0,则该行会被删除。
如果列不在主键中且无法被汇总,则会在现有的值中任选一个。
主键所在的列中的值不会被汇总。
2.4 AggregatingMergeTree
会将所有排序健相同的行合并成1行,这一行会保存一系列聚合函数的结果。在建表时,表中的字段必须是AggregateFunction
或者SimpleAggregateFunction
这两种数据类型之一。
插入数据时必须使用insert select
语句,而且select
语句中必须带有State
结尾的聚合函数(聚合函数组合器)。下面进行举例:
- 先创建一张订单表:
1
2
3
4
5
6CREATE TABLE sale_order (order_id UInt16,
price UInt16,
product_name String,
create_day Date) ENGINE = MergeTree()
ORDER BY (order_id)
PARTITION BY toYYYYMM(create_day); - 新增数据到订单表
1
insert into sale_order values(1,100,'Redmi K20 PRO','2019-01-26'),(2,150,'洗衣机','2019-01-26'),(3,80,'电视机','2019-01-27'),(4,20,'ipad','2019-01-27'),(5,10,'艾瑞泽gx','2019-01-27');
- 创建聚合表(以
AggregateFunction
数据类型为例)1
2
3
4CREATE TABLE sale_order_aggretate (create_day Date,
sumPrice AggregateFunction(sum,UInt16),
uniProductName AggregateFunction(uniq,String)) ENGINE = AggregatingMergeTree()
ORDER BY (create_day); - 往聚合表新增数据
1
INSERT INTO sale_order_aggretate SELECT create_day ,sumState(price) as sumPrice ,uniqState(product_name) as uniProductName from sale_order group by create_day;
- 查询聚合表中的数据(按照创建日期分组,求每天的总销售额和卖出商品种类的数量),得到如下结果。
1
SELECT create_day ,sumMerge(sumPrice) as sumPrice ,uniqMerge(uniProductName) from sale_order_aggretate group by create_day;
create_day | sumPrice | uniqMerge(uniProductName) |
---|---|---|
2019-01-26 | 250 | 2 |
2019-01-27 | 110 | 3 |
在这里有3个要点,
INSERT INTO SELECT
语句中的聚合函数类型要和聚合表的字段声明的一致,同时聚合函数要使用State
结尾。- 第五步查询聚合表时,使用的聚合函数要用
Merge结尾
。 - 直接查询聚合表中的数据(不用
group by
),会得到乱码,因为聚合表是以二进制的形式保存的聚合中间结果。
当然我们也可以将物化表设置为AggregatingMergeTree
引擎。
AggregateFunction
和SimpleAggregateFunction
的区别:
AggregateFunction
保存的是中间值不能直接被使用,SimpleAggregateFunction
存储聚合函数的当前值,可以被直接使用。- 使用
AggregateFunction
数据类型在插入时必须使用State
结尾的聚合函数,查询该字段时也要使用Merge
结尾的聚合函数,而SimpleAggregateFunction
则无此限制。 AggregateFunction
支持的聚合函数比SimpleAggregateFunction
多。- 对于同一种聚合函数优先使用
SimpleAggregateFunction
,他的效率比AggregateFunction
高。
2.5 ReplacingMergeTree
该表会在合并时删除排序健相同的重复数据。因为合并是不定期的,所以ReplacingMergeTree也不能保证表中一定不存在重复数据。当然你也在新增完数据之后手动触发合并。
2.6 Log系列
log系列引擎因为只适合小数据(1百万行数据左右)的小表使用,在正式应用中很少,所以不再多做介绍。