文章目录
- 一、表引擎
- 1、表引擎的作用
- 2、TinyLog
- 3、Memory
- 4、MergeTree
- 二、数据库引擎
- 1、作用--跨种类交换数据
- 2、示例
- 三、MergeTree引擎
- 1、简单使用
- 2、分区partition by
- 3、主键primary key
- 4、order by(必填)
一、表引擎
1、表引擎的作用
CK表引擎决定了如何存储表的数据。包括:
➢ 数据的存储方式和位置,写到哪里以及从哪里读取数据。
➢ 支持哪些查询以及如何支持。
➢ 并发数据访问。
➢ 索引的使用(如果存在)。
➢ 是否可以执行多线程请求。
➢ 数据复制参数。
表引擎的使用方式就是必须显式在创建表时定义该表使用的引擎,以及引擎使用的相关参数。
特别注意:==引擎的名称大小写敏感==
2、TinyLog
- 以列文件的形式保存在磁盘上
- 不支持索引
- 没有并发控制
- 一般保存少量数据的小表,产环境上作用有限。可以用于平时练习测试用
create table t_tinylog ( id String, name String) engine=TinyLog;
3、Memory
- 内存引擎,数据以未压缩的原始形式直接保存在内存当中,服务器重启数据就会消失
- 读写操作不会相互阻塞,不支持索引
- 简单查询下有非常非常高的性能表现(超过 10G/s)
- 常用于测试、在需要非常高的性能,同时数据量又不太大(上限大概 1 亿行)的场景场景
4、MergeTree
- ClickHouse 中最强大的表引擎当属 MergeTree(合并树)引擎及该系列(*MergeTree)中的其他引擎
- 支持索引和分区
- 地位可以相当于 innodb 之于 Mysql
- 基于 MergeTree还衍生出了很多小弟,即*MergeTree系列
二、数据库引擎
1、作用–跨种类交换数据
除了表引擎,CK还有数据库引擎,如MySQL引擎
MySQL引擎用于
将远程的MySQL服务器中的表映射到ClickHouse中
,并允许您对表进行INSERT
和SELECT
查询,以方便您在ClickHouse与MySQL之间进行数据交换
CREATE DATABASE [IF NOT EXISTS] db_name [ON CLUSTER cluster]
ENGINE = MySQL('host:port', ['database' | database], 'user', 'password')
- host:port — MySQL服务地址
- database — MySQL数据库名称
- user — MySQL用户名
- password — MySQL用户密码
2、示例
CK支持的数据库引擎很多,这里以MySQL为例:先在MySQL中准备测试数据:
mysql> USE testDB;
Database changed
mysql> CREATE TABLE `mysql_table` (
-> `int_id` INT NOT NULL AUTO_INCREMENT,
-> `float` FLOAT NOT NULL,
-> PRIMARY KEY (`int_id`));
Query OK, 0 rows affected (0,09 sec)
mysql> insert into mysql_table (`int_id`, `float`) VALUES (1,2);
Query OK, 1 row affected (0,00 sec)
mysql> select * from mysql_table;
+------+---------+
| int_id | value |
+------+---------+
| 1 | 2 |
+------+---------+
1 row in set (0,00 sec)
ClickHouse中的数据库,与MySQL服务器交换数据:
CREATE DATABASE mysql_db
ENGINE = MySQL('localhost:3306', 'testDB', 'my_user', 'user_password')
SHOW DATABASES;
┌─name─────┐
│ default │
│ mysql_db │
│ system │
└──────────┘
SELECT * FROM mysql_db.mysql_table;
┌─int_id─┬─value─┐
│ 1 │ 2 │
└────────┴───────┘
INSERT INTO mysql_db.mysql_table VALUES (3,4);
SELECT * FROM mysql_db.mysql_table;
┌─int_id─┬─value─┐
│ 1 │ 2 │
│ 3 │ 4 │
└────────┴───────┘
三、MergeTree引擎
1、简单使用
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);
以上创建表时,使用MergeTree引擎,primary key和MySQL不同的是,该引擎的主键也会加索引,但却没有唯一性约束
insert into t_order_mt values
(101,'sku_001',1000.00,'2020-06-01 12:00:00') ,
(102,'sku_002',2000.00,'2020-06-01 11:00:00'),
(102,'sku_004',2500.00,'2020-06-01 12:00:00'),
(102,'sku_002',2000.00,'2020-06-01 13:00:00'),
(102,'sku_002',12000.00,'2020-06-01 13:00:00'),
(102,'sku_002',600.00,'2020-06-02 12:00:00');
2、分区partition by
分区的目的主要是
降低扫描的范围
,优化查询速度。可选,不填则只有一个分区。
➢ 分区目录:MergeTree 是以列文件+索引文件+表定义文件组成的,但是如果设定了分区那么这些文件就会保存到不同的分区目录中
20200601_1_1_0含义解释:
PartitionId_MinBlockNum_MaxBlockNum_Level
分区值_最小分区块编号_最大分区块编号_合并层级
---------------
1)PartitionId
数据分区ID生成规则:
数据分区规则由分区ID决定,分区ID由PARTITION BY分区键决定。根据分区键字段类型,ID生成规则可分为:
- 未定义分区键:
没有定义PARTITION BY,默认生成一个目录名为all的数据分区,所有数据均存放在all目录下。
- 整型分区键:
分区键为整型,那么直接用该整型值的字符串形式做为分区ID。
- 日期类分区键:
分区键为日期类型,或者可以转化成日期类型。
- 其他类型分区键:
String、Float类型等,通过128位的Hash算法取其Hash值作为分区ID。
2)MinBlockNum
最小分区块编号,自增类型,从1开始向上递增。每产生一个新的目录分区就向上递增一个数字。
3)MaxBlockNum
最大分区块编号,新创建的分区MinBlockNum等于MaxBlockNum的编号。
4)Level
合并的层级,被合并的次数。合并次数越多,层级值越大。
➢ 并行:分区后,面对跨分区的查询统计,CK会一个线程处理一个分区,并行查
cd /var/lib/clickhouse
# data、metadata等目录中存在CK中的数据和元数据
cd /20200601_1_1_0
# bin文件:数据文件
# mrk文件:标记文件
# 标记文件在idx索引文件和bin数据文件之间起到了桥梁作用,以mrk2结尾的文件,表示启动了自适应索引间隔
# primary.idx文件:主键索引文件,用于加快查询效率
# minmax_create_time.id:分区键的最大最小值
# checksums.txt:校验文件,用于校验各个文件的正确性,存放各个文件的size以及hash值
➢ 数据写入与分区合并:任何一个批次的数据写入都会产生一个临时分区,不会纳入任何一个已有的分区。写入后的某个时刻(大概 10-15 分钟后),ClickHouse 会自动执行合并操作(等不及也可以手动通过 optimize 执行),把临时分区的数据,合并到已有分区中。
optimize table xxxx final;
继续再插入一遍上面的数据,查看分区效果:
insert into t_order_mt values
(101,'sku_001',1000.00,'2020-06-01 12:00:00') ,
(102,'sku_002',2000.00,'2020-06-01 11:00:00'),
(102,'sku_004',2500.00,'2020-06-01 12:00:00'),
(102,'sku_002',2000.00,'2020-06-01 13:00:00'),
(102,'sku_002',12000.00,'2020-06-01 13:00:00'),
(102,'sku_002',600.00,'2020-06-02 12:00:00');
可以看到数据并没有合并:
分区目录长这样:
接下来手动执行合并:
optimize table t_order_mt final;
效果:
两个合并的目录就是过期数据了,后期会被清理掉。再看SQL中的效果:
最后,手动合并分区,还可以只选其中一个分区。如上面表中的两个分区,我只合并20200621分区
optimize table t_order_mt partitior '20200621' final;
3、主键primary key
CK中的主键,只提供了数据的一级索引,但是却不是唯一约束
,即可以存在相同 primary key 的数据的。说CK主键的作用前,先了解下稀疏索引。
index granularity: 直接翻译的话就是
索引粒度
,指在稀疏索引中两个相邻索引对应数据的间隔
。ClickHouse 中的 MergeTree 默认是 8192。官方不建议修改这个值,除非该列存在大量重复值,比如在一个分区中几万行才有一个不同数据。
稀疏索引:
稀疏索引的好处就是可以用很少的索引数据,定位更多的数据,代价就是只能定位到索引粒度的第一行,然后再进行一点扫描。
主键的设定主要依据是查询语句中的 where 条件。根据条件通过对主键进行某种形式的二分查找,能够定位到对应的 index granularity,避免了全表扫描。
4、order by(必填)
order by 设定了
分区内的数据
按照哪些字段顺序进行有序保存。
order by 是 MergeTree 中唯一一个必填项,因为当用户不设置主键时,很多操作要依靠order by的字段,比如索引查找、去重和汇总
主键必须是 order by 字段的前缀字段。
比如 order by 字段是 (id,sku_id) 那么主键必须是 id 或者(id,sku_id)