clickhouse
一、表引擎使用
表引擎是Clickhouse的一大特色,可以说,表引擎决定了如何存储表的数据。
包括:
数据的存储方式和位置,写到哪里以及从哪里读取数据
支持哪些查询以及如何支持
并发数据访问
索引的使用(如果存在)
是否可以执行多线程请求
数据复制参数
二、TinyLog
日志家族,以列文件形式存储在磁盘,不支持索引,没有并发控制,一般保存少量数据的小表
一般临时测试用,数据量小于100w行
三、Memory
基于没存,查询快,安全性差,当服务器宕机就不能用了。
不能在生产环境中使用,也是主要测试使用,数据量不大的情况。
四、MergeTree(重点)
合并树,支持索引和分区,相当于innodb之于MySQL
注意:Clickhouse表主键可以重复,没有唯一约束
为了测试,我们先建一张表,插入一些数据
建表:
create table t_order_mt(
id UInt32,
sku_id String,
total_count Decimal(16,2),
create_time Datetime
) engine = MergeTree
partition by toYYYYMMDD(create_time)
order BY (id,sku_id);
partition by 分区
order by 排序
engine 指定搜索引擎
插入数据:
INSERT into t_order_mt values
(101,'sku_001',1000.00,'2020-06-01 12:00:00'),
(102,'sku_002',2000.00,'2020-06-02 12:00:00'),
(103,'sku_001',2500.00,'2020-06-02 12:00:00'),
(102,'sku_003',2300.00,'2020-06-01 12:00:00'),
(101,'sku_001',1800.00,'2020-06-01 12:00:00');
查询数据:
SELECT * from t_order_mt;
持久化的数据默认存储在 /var/lib/clickhouse中
partition by
主要为了进行分区,避免全表扫描,优化查询速度
如果不写分区,就会生成一个all目录文件,所有的数据索引都会存在里面
分区文件夹:
data.bin 数据文件(存储真实数据)
.mrk 标记文件(记录字段偏移量)
-
count.txt 记录数据总记录数,每次查询总记录数响应时间短也是因为将这个数据保存到文件中了,
每次写入都会修改这个文件的总记录数的数据
columns.txt 记录列的信息
primary.idx 主键的索引文件(稀疏索引)
partition.dat 分区文件
当我们再次添加数据到表中,查询表中数据发现又进行了分区,这里是因为后插入的数据会加入临时分区,等到合并操作才会进行合并整合。
┌──id─┬─sku_id──┬─total_count─┬─────────create_time─┐
│ 101 │ sku_001 │ 1000 │ 2020-06-01 12:00:00 │
│ 101 │ sku_001 │ 1800 │ 2020-06-01 12:00:00 │
│ 102 │ sku_003 │ 2300 │ 2020-06-01 12:00:00 │
└─────┴─────────┴─────────────┴─────────────────────┘
┌──id─┬─sku_id──┬─total_count─┬─────────create_time─┐
│ 101 │ sku_001 │ 1000 │ 2020-06-01 12:00:00 │
│ 101 │ sku_001 │ 1000 │ 2020-06-01 12:00:00 │
└─────┴─────────┴─────────────┴─────────────────────┘
┌──id─┬─sku_id──┬─total_count─┬─────────create_time─┐
│ 102 │ sku_002 │ 2000 │ 2020-06-02 12:00:00 │
│ 103 │ sku_001 │ 2500 │ 2020-06-02 12:00:00 │
关于合并操作,系统通常会在某一时刻进行合并操作(10~15分钟)
也可以手动触发
optimize table xxx final;
这是合并所有 同一个分区键的数据,我们也可以合并指定分区键的数据。
optimize table xxx partition 键名 final;
当我们进行合并
optimize table t_order_mt final;
查看文件目录后发现
这里 1_1_0 和 3_3_0 合并为 1_3_1
含义是:最小分区编号最大分区编号合并次数
同一个分区键 20200601 进行了合并
分区键
partition 后的关键字(字段)
未定义分区键:默认生成一个目录名为all的数据分区
整型分区键:直接用该整型值的字符串形式作为分区ID
-
日期类型分区键:分区键为日期类型。如果是 日期形式的字符串 会自动转为日期类型
直接使用日期类型 效率更高
其他类型分区键:String、Float等,通过Hash算法 取其Hash值作为分区ID
primary key主键(可选)
主键没有唯一约束,只提供数据的一级索引,并且这个索引是稀疏索引(避免存储重复数据,以及全表扫描)
关于稀疏索引,有一个磨人的 索引粒度 index granularity 指在稀疏索引中两个相邻索引对应数据的间隔。
Clickhouse中MergeTree默认是8192,如果重复数据远大于8192可以相应调大。
order by(必选)
order by 设定了分区内的数据按照哪些字段顺序进行有序保存
order by 是MergeTree的唯一一个必选项,甚至比primary key还重要,因为用户不设置主键 很多处理会按照order by的字段进行处理(比如后面会讲的去重和汇总)
要求:主键必须是order by 字段的前缀字段
比如order by字段是(id,sku_id)name主键必须是id 或者(id,sku_id)
TTL 过期
过期设置可以对 列 或者 对表 进行过期,到期后对数据默认进行delete操作。
也可以进行移动数据操作
操作:
- Delete
- To Disk 'aaa'
- To VOLUME 'bbb'
- GROUP BY
ReplacingMergeTree
是MergeTree的一个变种,多一个去重功能,尽管MergeTree可以设置主键
根据order by 的自动去重,不根据主键去重
去重时机:
数据的去重只会在合并的过程中出现。合并会在未知的时间在后台进行,所以你无法预先作出计划。有一些数据可能仍未被处理。
无法控制去重时机
去重范围:
分区内进行合并去重
结论:
- 实际上是使用order by字段作为唯一键
- 去重不能跨分区
- 只有同一批插入(新版本)或合并分区时才会进行去重
- 认定重复的数据保留,版本字段值最大的
- 如果版本字段相同则按插入顺序保留最后一笔
SummingMergeT ree
做聚合的MergeTree子类
- 分区内聚合
- 不是实时聚合,分片合并才会聚合
- 以SummingMergeTree() 中指定到列作为汇总数据列
- 可以填写多列必须数字列,如果不填,以所有非纬度列且为数字列的字段为汇总数据列
- 以order by 的列为准,作为纬度列
- 其他的列按插入顺序保留第一行
- 不在一个分区的数据不会被整合
五、外部引擎
就是将Clickhouse中的数据通过映射其他数据库的数据,不需要我们进行数据的导入导出