【ClickHouse】

一、表引擎

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中,并允许您对表进行INSERTSELECT查询,以方便您在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─┐
│      12 │
└────────┴───────┘
INSERT INTO mysql_db.mysql_table VALUES (3,4);
SELECT * FROM mysql_db.mysql_table;

┌─int_id─┬─value─┐
│      12 │
│      34 │
└────────┴───────┘

三、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的编号。
  
4Level
   合并的层级,被合并的次数。合并次数越多,层级值越大。

并行:分区后,面对跨分区的查询统计,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)

猜你喜欢

转载自blog.csdn.net/llg___/article/details/130831857