表引擎的作用:
➢ 数据的存储方式和位置,写到哪里以及从哪里读取数据。集成mysql,kakfa等
➢ 支持哪些查询以及如何支持。
➢ 并发数据访问。
➢ 索引的使用(如果存在)。
➢ 是否可以执行多线程请求。
➢ 数据复制参数。
这种引擎必须显式的在创建表的时候定义,注意:大小写敏感!
分类:日志引擎,集成引擎(可以通过ck进行其他存储的查询与插入等)
TinyLog
以列文件的形式保存在磁盘上,不支持索引,没有并发控制。一般保存少量数据的小表,生产环境上作用有限。可以用于平时练习测试用。例:engine=TinyLog;
Memory
内存引擎,数据以未压缩的原始形式直接保存在内存当中,服务器重启数据就会消失。
读写操作不会相互阻塞,不支持索引。简单查询下有非常非常高的性能表现(超过 10G/s)。
一般用到它的地方不多,除了用来测试,就是在需要非常高的性能,同时数据量又不太
大(上限大概 1 亿行)的场景。
MergeTree(重中之重)
ClickHouse 中最强大的表引擎当属 MergeTree(合并树)引擎及该系列(*MergeTree)
中的其他引擎,支持索引和分区,地位可以相当于 innodb 之于 Mysql。
而且基于 MergeTree,还衍生除了很多小弟,也是非常有特色的引擎。
建表语句:
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);
插入语句:
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');
主键可以重复;
端口默认8123;
- partition by 分区(可选)
分区的目的主要是降低扫描的范围,优化查询速度
分区目录:MergeTree 是以列文件+索引文件+表定义文件组成的,但是如果设定了分区那么这些文件就会保存到不同的分区目录中。
PartitionId_MinBlockNum_MaxBlockNum_Level
分区值_最小分区块编号_最大分区块编号_合并层级 =》PartitionId
=》MinBlockNum
最小分区块编号,自增类型,从1开始向上递增。每产生一个新的目录分区就向上递增一个数字。合并块里面的最小编号
=》MaxBlockNum
最大分区块编号,新创建的分区MinBlockNum等于MaxBlockNum的编号。合并块里面的最大编号
=》Level
合并的层级,被合并的次数。合并次数越多,层级值越大。它是单张表中的单个分区内累加的,每当新创建一个分区目录其值均为0,只有当分区目录发生合并时其值才会大于0。
数据分区ID生成规则
数据分区规则由分区ID决定,分区ID由PARTITION BY分区键决定。
根据分区键字段类型,ID生成规则可分为:
- 未定义分区键
没有定义PARTITION BY,默认生成一个目录名为all的数据分区,所有数据均存放在all目录下。
- 整型分区键
分区键为整型,那么直接用该整型值的字符串形式做为分区ID。
- 日期类分区键
分区键为日期类型,或者可以转化成日期类型。
- 其他类型分区键
String、Float类型等,通过128位的Hash算法取其Hash值作为分区ID。
bin文件:数据文件
mrk文件:标记文件,标记文件在 idx索引文件 和 bin数据文件 之间起到了桥梁作用。 以mrk2结尾的文件,表示该表启用了自适应索引间隔。
primary.idx文件:主键索引文件,用于加快查询效率。
minmax_create_time.idx:分区键的最大最小值。
checksums.txt:校验文件,用于校验各个文件的正确性。存放各个文件的size以及hash值。
count.txt:计数文件,用于记录当前分区目录下数据的总行数
数据写入与分区合并
任何一个批次的数据写入都会产生一个临时分区,不会纳入任何一个已有的分区。写入后的某个时刻(大概 10-15 分钟后),ClickHouse 会自动执行合并操作(等不及也可以手动通过 optimize 执行),把临时分区的数据,合并到已有分区中。
optimize table xxxx final;
optimize table xxxx partition 'xxxxx' final;指定分区合并
- primary key 主键(可选)
ClickHouse 中的主键,和其他数据库不太一样,它只提供了数据的一级索引,但是却不是唯一约束。这就意味着是可以存在相同 primary key 的数据的。主键的设定主要依据是查询语句中的 where 条件。根据条件通过对主键进行某种形式的二分查找,能够定位到对应的 index granularity,避免了全表扫描。
index granularity: 直接翻译的话就是索引粒度,指在稀疏索引中两个相邻索引对应数
据的间隔。ClickHouse 中的 MergeTree 默认是 8192。官方不建议修改这个值,除非该列存在大量重复值,比如在一个分区中几万行才有一个不同数据。
稀疏索引的好处就是可以用很少的索引数据,定位更多的数据,代价就是只能定位到索引粒度的第一行,然后再进行进行一点扫描。
- order by(必选)
order by 设定了分区内的数据按照哪些字段顺序进行有序保存。
order by 是 MergeTree 中唯一一个必填项,甚至比 primary key 还重要,因为当用户不
设置主键的情况,很多处理会依照 order by 的字段进行处理(比如后面会讲的去重和汇总)。
要求:主键必须是 order by 字段的前缀字段。
比如 order by 字段是 (id,sku_id) 那么主键必须是 id 或者(id,sku_id)。
- 二级索引(跳数索引)
默认是开启的
例:
create table t_order_mt2(
id UInt32,
sku_id String,
total_amount Decimal(16,2),
create_time Datetime,
INDEX a total_amount TYPE minmax GRANULARITY 5
) engine =MergeTree
partition by toYYYYMMDD(create_time)primary key (id)
order by (id, sku_id);
其中 GRANULARITY N 是设定二级索引对于一级索引粒度的粒度。
解释:二级索引的粒度即为一级索引的块数*N,在这里就是1-8192*5
MergeTree共支持4种跳数索引,分别是minmax、set、ngrambf_v1和tokenbf_v1。一张数据表支持同时声明多个跳数索引
(1)minmax:minmax索引记录了一段数据内的最小和最大极值,其索引的作用类似分区目录的minmax索引,能够快速跳过无用的数据区间,示例如下所示:
INDEX a ID TYPE minmax GRANULARITY 5
上述示例中minmax索引会记录这段数据区间内ID字段的极值。极值的计算涉及每5个index_granularity区间中的数据。
(2)set:set索引直接记录了声明字段或表达式的取值(唯一值,无重复),其完整形式为set(max_rows),其中max_rows是一个阈值,表示在一个index_granularity内,索引最多记录的数据行数。如果max_rows=0,则表示无限制,例如:
INDEX b(length(ID) * 8) TYPE set(100) GRANULARITY 5
上述示例中set索引会记录数据中ID的长度*8后的取值。其中,每个index_granularity内最多记录100条。
(3)ngrambf_v1:ngrambf_v1索引记录的是数据短语的布隆表过滤器,只支持String和FixedString数据类型。ngrambf_v1只能够提升in、notIn、like、equals和notEquals查询的性能,其完整形式为ngrambf_v1(n,size_of_bloom_filter_in_bytes,number_of_hash_functions,random_seed)。这些参数是一个布隆过滤器的标准输入,如果你接触过布隆过滤器,应该会对此十分熟悉。它们具体的含义如下:
·n:token长度,依据n的长度将数据切割为token短语。
·size_of_bloom_filter_in_bytes:布隆过滤器的大小。
·number_of_hash_functions:布隆过滤器中使用Hash函数的个数。
·random_seed:Hash函数的随机种子。
例如在下面的例子中,ngrambf_v1索引会依照3的粒度将数据切割成短语token,token会经过2个Hash函数映射后再被写入,布隆过滤器大小为256字节。
INDEX c(ID,Code) TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 5
(4)tokenbf_v1:tokenbf_v1索引是ngrambf_v1的变种,同样也是一种布隆过滤器索引。tokenbf_v1除了短语token的处理方法外,其他与ngrambf_v1是完全一样的。tokenbf_v1会自动按照非字符的、数字的字符串分割token,具体用法如下所示:
INDEX d ID TYPE tokenbf_v1(256, 2, 0) GRANULARITY 5
- 数据 TTL
TTL 即 Time To Live,MergeTree 提供了可以管理数据表或者列的生命周期的功能。
(1)列级别TTL
create table t_order_mt3(
id UInt32,
sku_id String,
total_amount Decimal(16,2) TTL create_time+interval 10 SECOND,
create_time Datetime
) engine =MergeTree
partition by toYYYYMMDD(create_time)
primary key (id)
order by (id, sku_id);
(2)表级TTL
下面的这条语句是数据会在 create_time 之后 10 秒丢失
alter table t_order_mt3 MODIFY TTL create_time + INTERVAL 10 SECOND;
涉及判断的字段必须是 Date 或者 Datetime 类型,推荐使用分区的日期字段。
能够使用的时间周期:
- SECOND
- MINUTE
- HOUR
- DAY
- WEEK
- MONTH
- QUARTER
- YEAR