ClickHouse
起源
ClickHouse 是由号称“俄罗斯 Google”的 Yandex 开发而来,在 2016 年开源.在计算引擎里算是一个后起之秀,在数据库领域号称是最快的.
是什么
ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS)。
OLAP / OLTP
OLAP,也叫联机分析处理(Online Analytical Processing)系统,有的时候也叫DSS决策支持系统,就是我们说的数据仓库。与此相对的是OLTP(on-line transaction processing)联机事务处理系统。可以看出一个侧重事务处理。一个侧重分析处理
列式 / 行式
ID | NAME | AGE |
---|---|---|
1 | a | 10 |
2 | b | 20 |
ID | 1 | 2 |
---|---|---|
NAME | a | b |
AGE | 10 | 20 |
Row-store | 1 | a | 10 | 2 | b | 20 |
---|---|---|---|---|---|---|
Col-store | 1 | 2 | a | b | 10 | 20 |
- 行式:一行的数据存储在一起
- 列式:一列的数据存储在一起
行式存储 | 列式存储 | |
---|---|---|
优点 | 1.数据保存在一起,对某一行数据查询效率高 2. Insert/Update比较容易 | 1.以列存储每一列都可以作为索引 2.只查询某几列只需要读取某几列的数据,避免不必要的开销。3.一列数据类型的数据便于高效的压缩 |
缺点 | 1.只需要某几列数据时所有数据会被抓取 | 1.INSERT/UPDATE比较麻烦 2.选择某几列需要进行重新组装 |
DBMS
是一个数据库管理系统也就是说它是一个成体系的东西,对于数据的读写、存储、查询、修改、复制、事务、效率等等方方面面都有自己的一套东西
优点
- 超高性能:
- 数据压缩空间大单服务器每秒处理几亿行,HBase,BigTable,Cassandra,等只能提供每秒数十万的吞吐能力
- 真正的列式数据库管理系统进行简单的查询单服务器每秒可达2TB
- SQL语法丰富
- 驱动丰富
- 向量化引擎:
- 写入速度快,lsm树模型数据直接顺序写入磁盘(和kafka类似),普通磁盘能到50M-200M/s
- 线性扩展
- 横向扩展,可以部署在成百上千的节点上
- 纵向扩展,单个节点可以容纳万亿行超过100TB的数据
- 功能多
- 多个表引擎适用于复杂多元的业务
- 支持数据分片数据备份
- 不依赖于Hadoop庞大的生态
不足
- 没有完整的事务支持
- 不支持高并发: 每个查询都是尽量使用全部服务器资源
- 缺少高频率,低延迟的修改或删除已存在数据的能力。仅能用于批量删除或修改数据
- 稀疏索引使得ClickHouse不适合通过其键检索单行的点查询。
哪些公司在使用
-
Yandex.Metrica :目前为止,该系统在ClickHouse中有超过13万亿条记录,并且每天超过200多亿个事件被处理
-
今日头条:用ClickHouse来做用户行为分析,内部一共几千个ClickHouse节点,单集群最大1200节点,总数据量几十PB,日增原始数据300TB左右
-
腾讯:内部用ClickHouse做游戏数据分析,并且为之建立了一整套监控运维体系。
-
携程:内部从18年7月份开始接入试用,目前80%的业务都跑在ClickHouse上。每天数据增量十多亿,近百万次查询请求
数据类型
MYSQL | Hive | ClickHouse(区分大小写) |
---|---|---|
Byte | tinyint | Int8 / UInt8 |
short | smallint | Int16 / UInt16 |
int | int | Int32 / UInt32 |
long | bigint | Int64 / UInt64 |
varchar | string | String |
timestamp | timestamp | DateTime |
float | float | Float32 |
double | double | Float64 |
-
Nullable:允许用特殊标记 (NULL) 表示"缺失值",可以与
TypeName
的正常值存放一起,官方介绍使用该类型总是会拖累性能,假设有业务需要null值的可以给它一个数据里不存在的比如都是正数的数据,可以定义-1为null值 -
FixedString(N): 不推荐使用
- 如果字符串包含的字节数少于`N’,将对字符串末尾进行空字节填充
- 如果字符串包含的字节数大于
N
,将抛出Too large value for FixedString(N)
异常 - 当做数据查询时,ClickHouse不会删除字符串末尾的空字节. 如果使用
WHERE
子句,则须要手动添加空字节(\0)以匹配FixedString
的值
-
Array(T): 还不支持多维数组
- 数组中只能有T类型元素和NULL(使用了Nullable包装)
-
Enum8/Enum16:
Enum
保存'string'= integer
的对应关系- 底层存储的数字,工作机制与它们在底层数值上的工作机制相同。如在ORDER BY
,
GROUP BY,
IN,
DISTINCT中Enum 的行为与相应的数字相同 - 大多数具有数字和字符串的运算并不适用于Enums;例如,Enum 类型不能和一个数值相加
- 底层存储的数字,工作机制与它们在底层数值上的工作机制相同。如在ORDER BY
-
Domain类型:
- IPv4:
IPv4
是与UInt32
类型保持二进制兼容的Domain类型 - IPv6:
IPv6
是与FixedString(16)
类型保持二进制兼容的Domain类型
- IPv4:
默认值
数字类型 | 0 |
---|---|
String | ‘’ |
Date | 0000-00-00 |
DateTime | 0000-00-00 00:00:00 |
表引擎
表引擎(即表的类型)决定了:
- 数据的存储方式和位置,写到哪里以及从哪里读取数据
- 支持哪些查询以及如何支持。
- 并发数据访问。
- 索引的使用(如果存在)。
- 是否可以执行多线程请求。
- 数据复制参数。
Log
具有最小功能的轻量级引擎。当您需要快速写入许多小表(最多约100万行)并在以后整体读取它们时,该类型的引擎是最有效的
TinyLog
1.数据存储在磁盘
2.写入数据时追加到文件末尾
3.不支持并发
CREATE TABLE tiny(`id` UInt(32), `name` String,`age` UInt16)ENGINE = TinyLog
MergeTree
适用于高负载任务的最通用和功能最强大的表引擎。这些引擎的共同特点是可以快速插入数据并进行后续的后台数据处理。 MergeTree系列引擎支持数据复制(使用Replicated* 的引擎版本),分区和一些其他引擎不支持的其他功能。
MergeTree
1.支持分区,不支持类似hive的多级目录的分区,一般都以年月日做为分区
2.存储的数据分区内按照主键和排序字段排序,类似于mysql的联合索引(稀疏索引),需要根据业务考虑字段的先后顺序
3.稀疏索引: 对分区中排序好的数据每一段数据(默认8192)存储一个索引,这样索引占用空间就少 (类似于只有一级索引的跳表,可以实现二分查找)
3.支持数据副本
ENGINE = MergeTree()
[PARTITION BY expr] // 分区
[ORDER BY expr] // 表的排序键
[PRIMARY KEY expr] // 主键,默认和排序键相同,一般不需要设置
[SETTINGS name=value, ...] // 设置索引粒度和一些其他的配置
CREATE TABLE click.mt (`id` UInt16, `name` String, `age` UInt16, `birthDay` DateTime) ENGINE = MergeTree() PARTITION BY toYYYYMM(birthDay) ORDER BY (name, age) SETTINGS index_granularity = 8192
ReplacingMergeTree
1.该引擎和MergeTree的不同之处在于它会删除具有相同主键的重复项
2.去重合并会在后台运行,不保证没有重复数据出现
3.主键相同数据合并时如果ver列未指定会取最后一条,指定时取最大版本的(ver 类型为 UInt*, Date 或 DateTime)
CREATE TABLE click.rmt (`gmt` Date, `id` UInt16, `name` String, `point` UInt16) ENGINE = ReplacingMergeTree(point) PARTITION BY gmt ORDER BY name SETTINGS index_granularity = 8192
insert into t (gmt, id, name, point) values ('2017-07-11', 1, 'a', 20);
insert into t (gmt, id, name, point) value