ClickHouse 是俄罗斯的 Yandex 于 2016 年开源的用于在线分析处理查询(OLAP :Online Analytical Processing)MPP架构的列式存储数据库(DBMS:Database Management System),能够使用 SQL 查询实时生成分析数据报告。clickhouse可以做用户行为分析,流批一体,clickhouse没有走hadoop生态,采用 Local attached storage 作为存储。
列式存储:列式存储更符合OLAP数据库的使用。
DBMS的功能:几乎覆盖了标准SQL的大部分语法,包括 DDL和 DML ,以及配套的各种函数,使用方便。
多样化引擎:clickhouse
和mysql
类似,把表级的存储引擎插件化,根据表的不同需求可以设定不同的库引擎和表引擎。
高吞吐写入能力:ClickHouse采用类LSM Tree的结构,数据写入后定期在后台Compaction。通过类LSM tree的结构,ClickHouse在数据导入时全部是顺序append写,写入后数据段不可更改,在后台compaction时也是多个段merge sort后顺序写回磁盘。顺序写的特性,充分利用了磁盘的吞吐能力,即便在HDD上也有着优异的写入性能。
数据分区与线程级并行:ClickHouse
将数据划分为多个partition
,每个partition
再进一步划分为多个index granularity
,然后通过多个CPU核心分别处理其中的一部分来实现并行数据处理。在这种设计下,单条Query
就能利用整机所有CPU。极致的并行处理能力,极大的降低了查询延时。
更适合单表查询:ClickHouse 像很多 OLAP 数据库一样,单表查询速度优于关联查询,而且 ClickHouse的两者差距更为明显。(clickhouse会将右表加载到内存)。
高可用:通过数据Replacing,提供了高可用嫩里。
单表查询效率极高
1.整型
固定长度的整型,包括有符号整型或无符号整型。
整型范围(-2n-1~2n-1-1):
Int8 - [-128 : 127]
Int16 - [-32768 : 32767]
Int32 - [-2147483648 : 2147483647]
Int64 - [-9223372036854775808 : 9223372036854775807]
无符号整型范围(0~2n-1):
UInt8 - [0 : 255]
UInt16 - [0 : 65535]
UInt32 - [0 : 4294967295]
UInt64 - [0 : 18446744073709551615]
2.浮点型
Float32 - float
Float64 – double
建议尽可能以整数形式存储数据。例如,将固定精度的数字转换为整数值,如时间用毫秒为单位表示,因为浮点型进行计算时可能引起四舍五入的误差。
适用场景:一般数据值比较小,不涉及大量的统计计算,精度要求不高的时候。比如保存商品的重量。
3.布尔型
没有单独的类型来存储布尔值。可以使用 UInt8 类型,取值限制为 0 或 1。
4.Decimal型
有符号的浮点数,可在加、减和乘法运算过程中保持精度。对于除法,最低有效数字会被丢弃(不舍入)。
有三种声明:
Decimal32(s),相当于Decimal(9-s,s)
Decimal64(s),相当于Decimal(18-s,s)
Decimal128(s),相当于Decimal(38-s,s)
适用场景:一般金额字段,汇率,利率等字段为了保证小数点精度,都是用Decimal进行存储。
5.字符串
1)String
字符串可以任意长度的。它可以包含任意的字节集,包含空字节。
2)FixedString(N)
固定长度 N 的字符串,N 必须是严格的正自然数。当服务端读取长度小于 N 的字符串时候,通过在字符串末尾添加空字节来达到 N 字节长度。 当服务端读取长度大于 N 的字符串时候,将返回错误消息。
与String相比,极少会使用FixedString,因为使用起来不是很方便。
适用场景:名称,文字描述,字符型编码。固定长度的可以保存一些定长的内容,比如一些编码,性别等,但是考虑到一定的变化风险,带来收益不够明显,所以定长字符串使用意义有限。
6.枚举类型
包括 Enum8 和 Enum16 类型。Enum 保存'string'= integer 的对应关系。
Enum8 用 'String'= Int8 对描述。
Enum16 用'String'= Int16对描述。
用法演示:
- --创建一个带有一个枚举 Enum8('hello' = 1, 'world' = 2) 类型的列:
-
- CREATE TABLE t_enum
- (
- x Enum8('hello' = 1, 'world' = 2)
- )
- ENGINE = TinyLog
适用场景:对于一些状态,类型的字段算是一种空间优化,也算是一种数据约束。但是实际使用中往往因为一些数据内容的变化增加一定的维护成本,甚至是数据丢失的问题。所以谨慎使用。
7.时间类型
目前clickhouse 有三种时间类型
Date 接受 年-月-日 的字符串比如 ‘2019-12-16’
Datetime 接受 年-月-日 时:分:秒 的字符串比如 ‘2019-12-16 20:50:10’
Datetime64 接受 年-月-日 时:分:秒.亚秒 的字符串比如 ‘2019-12-16 20:50:10.66’
TinyLog
以列文件的形式保存在磁盘上,不支持索引,没有并发控制。一般保存少量数据的小表,生产环境上作用有限。可以用于平时练习测试用。
Memory
内存引擎,数据以未压缩的原始形式直接保存在内存当中,服务器重启数据就会消失。读写操作不会相互阻塞,不支持索引。简单查询下有非常非常高的性能表现(超过10G/s)。
一般用到它的地方不多,除了用来测试,就是在需要非常高的性能,同时数据量又不太大(上限大概 1 亿行)的场景。
MergeTree
Clickhouse 中最强大的表引擎当属 MergeTree (合并树)引擎及该系列(MergeTree)中的其他引擎。地位可以相当于innodb之于Mysql。 而且基于MergeTree,还衍生出了很多小弟,也是非常有特色的引擎。
合并过程:详解clickhouse分区目录的合并过程_大大大大肉包的博客-CSDN博客
- create table t_order_mt(
- id UInt32,
- sku_id String,
- total_amount Decimal(16,2),
- create_time Datetime
- ) engine =MergeTree
- partition by toYYYYMMDD(create_time)
- primary key (id)
- order by (id,sku_id)
- ;
ReplacingMergeTree
ReplacingMergeTree是MergeTree的一个变种,它存储特性完全继承MergeTree,只是多了一个去重的功能。
尽管MergeTree可以设置主键,但是primary key其实没有唯一约束的功能。如果你想处理掉重复的数据,可以借助这个ReplacingMergeTree。
去重时机:数据的去重只会在合并的过程中和同一批插入的数据中出现。合并会在未知的时间在后台进行,所以你无法预先作出计划。有一些数据可能仍未被处理。
去重范围:如果表经过了分区,去重只会在分区内部进行去重,不能执行跨分区的去重。
所以ReplacingMergeTree能力有限, ReplacingMergeTree 适用于在后台清除重复的数据以节省空间,但是它不保证没有重复的数据出现。
手动去重
optimize table t_order_smt final;
ReplacingMergeTree()
填入的参数为版本字段,重复数据保留版本字段值最大的。
如果不填版本字段,默认保留最后一条。
- create table t_order_rmt(
- id UInt32,
- sku_id String,
- total_amount Decimal(16,2) ,
- create_time Datetime
- ) engine =ReplacingMergeTree(create_time)
- partition by toYYYYMMDD(create_time)
- primary key (id)
- order by (id, sku_id)
SummingMergeTree
对于不查询明细,只关心以维度进行汇总聚合结果的场景。如果只使用普通的MergeTree的话,无论是存储空间的开销,还是查询时临时聚合的开销都比较大。
Clickhouse 为了这种场景,提供了一种能够“预聚合”的引擎,SummingMergeTree。
以SummingMergeTree()中指定的列作为汇总数据列。可以填写多列必须数字列,如果不填,以所有非维度列且为数字列的字段为汇总数据列。以order by 的列为准,作为维度列。其他的列保留第一行。不在一个分区的数据不会被聚合。