1.日志引擎
具有最小功能的轻量级引擎。当您需要快速写入许多小表(最多约100万行)并在以后整体读取它们时,该类型的引擎是最有效的。
1.1日志引擎的共同属性为:
- 数据存储在磁盘上;
- 写数据都是以追加的方式往文件里写数据;
- 有支持并发数据访问的锁:在
INSERT
查询期间,表被锁定,并且其他用于读取和写入数据的查询都等待表解锁。如果没有数据写入查询,那么可以同时执行任意数量的数据读取查询; - 不支持索引:这句话的意思是,select查询的数据范围效率不是很高
- 不要原子性的写数据:如果某些操作中断了写操作(例如,异常关闭服务器),则可能会导致表中的数据已损坏。
1.2 日志引擎的不同属性:
TinyLog
引擎是该系列中最简单的引擎,功能最差,效率最低。该TinyLog
引擎不支持通过单个查询中的多个线程进行并行数据读取。它比支持单个查询并行读取的系列中其他引擎读取数据的速度慢,并且使用几乎与Log
引擎一样多的文件描述符,因为它将每一列存储在单独的文件中。仅在简单情况下使用它。(对tinylog引擎的理解:因为使用tinylog引擎数据部分快,不支持 文件的分区,所以单个查询多线程并行的读取数据)
在Log
和StripeLog
引擎支持并行数据读取。读取数据时,ClickHouse使用多个线程。每个线程处理一个单独的数据块。该Log
引擎使用对表的每列一个单独的文件。StripeLog
将所有数据存储在一个文件中。结果,StripeLog
引擎使用更少的文件描述符,但是Log
引擎在读取数据时提供了更高的效率。
1.3 TinyLog引擎
该表引擎通常与一次写入方法一起使用:一次写入数据,然后根据需要多次读取。例如,您可以将TinyLog
-type表用于小批量处理的中间数据。请注意,将数据存储在大量小表中效率很低。
查询在单个流中执行。换句话说,此引擎旨在用于相对较小的表(最多约1,000,000行)。如果您有许多小表,则使用此表引擎很有意义,因为它比日志引擎更简单(需要打开的文件更少)
建表以及表的目录结构:
create table tb_tlog(
uid Int16,
name String,
address String
)
engine=TinyLog;插入数据:
insert into tb_tlog values (1,'zxx','bj'),(2,'ww','nj'),(1,'ls','tj');
insert into tb_tlog values (3,'zxx','bj'),(4,'ww','nj'),(5,'ls','tj');
insert into tb_tlog values (6,'zxx','bj'),(7,'ww','nj'),(8,'ls','tj');目录结构:因为tinylog引擎对数部分块,所以在目录中没有块 所以的文件;
-rw-r-----. 1 clickhouse clickhouse 105 Oct 18 22:13 address.bin
-rw-r-----. 1 clickhouse clickhouse 108 Oct 18 22:13 name.bin
-rw-r-----. 1 clickhouse clickhouse 97 Oct 18 22:13 sizes.json
-rw-r-----. 1 clickhouse clickhouse 96 Oct 18 22:13 uid.bin
1.4 StripLog引擎(数据分块所有的列都在一个文件中:data.bin):
在你需要写入许多小数据量(小于一百万行)的表的场景下使用这个引擎,
1.4.1 写数据
StripeLog 引擎将所有列存储在一个文件中。对每一次 Insert 请求,ClickHouse 将数据块追加在表文件的末尾,逐列写入。
ClickHouse 为每张表写入以下文件:
data.bin — 数据文件。
index.mrk — 带标记的文件。标记包含了已插入的每个数据块中每列的偏移量。
StripeLog 引擎不支持 ALTER UPDATE 和 ALTER DELETE 操作。
1.4.2 读数据
带标记的文件使得 ClickHouse 可以并行的读取数据。这意味着 SELECT 请求返回行的顺序是不可预测的。使用 ORDER BY 子句对行进行排序。
我们使用两次 INSERT 请求从而在 data.bin 文件中创建两个数据块。
ClickHouse 在查询数据时使用多线程。每个线程读取单独的数据块并在完成后独立的返回结果行。这样的结果是,大多数情况下,输出中块的顺序和输入时相应块的顺序是不同的
1.5 Log引擎(数据分块记录偏移量)
日志与 TinyLog 的不同之处在于,«标记» 的小文件与列文件存在一起。这些标记写在每个数据块上,并且包含偏移量,这些偏移量指示从哪里开始读取文件以便跳过指定的行数。这使得可以在多个线程中读取表数据。对于并发数据访问,可以同时执行读取操作,而写入操作则阻塞读取和其它写入。Log 引擎不支持索引。同样,如果写入表失败,则该表将被破坏,并且从该表读取将返回错误。Log 引擎适用于临时数据,write-once 表以及测试或演示目的。
2.MergeTree家族引擎:
MergeTree系列的表引擎是ClickHouse数据存储功能的核心。它们提供了用于弹性和高性能数据检索的大多数功能:列存储,自定义分区,稀疏的主索引,辅助数据跳过索引等。
基本MergeTree表引擎可以被认为是单节点ClickHouse实例的默认表引擎,因为它在各种用例中通用且实用。
对于生产用途,ReplicatedMergeTree是必经之路,因为它为常规MergeTree引擎的所有功能增加了高可用性。一个额外的好处是在数据提取时自动进行重复数据删除,因此如果插入过程中出现网络问题,该软件可以安全地重试。
MergeTree系列的所有其他引擎为某些特定用例添加了额外的功能。通常,它是作为后台的其他数据操作实现的。
MergeTree引擎的主要缺点是它们很重。因此,典型的模式是没有太多。如果您需要许多小表(例如用于临时数据),请考虑使用Log engine family。
主要特点:
- 存储按主键排序的数据。
这使您可以创建一个小的稀疏索引,以帮助更快地查找数据。
ClickHouse支持的某些分区操作比对相同数据,相同结果的常规操作更有效。ClickHouse还会自动切断在查询中指定了分区键的分区数据。这也提高了查询性能。
- 数据复制支持。
ReplicatedMergeTree表族提供数据复制。有关更多信息.
- 数据采样支持。
如有必要,可以在表中设置数据采样方法。
2.1 MergeTree引擎:
该MergeTree
系列中的引擎旨在将大量数据插入表中。数据快速地逐个部分写入表中,然后应用规则在后台合并这些部分。这种方法比插入期间连续重写存储中的数据效率更高。
每批次的插入数据作为一个基础单元进行分区,区内数据按照指定的字段进行排序
合并多次插入的分区: 合并之后会生成新的文件,当时间达到一定的阈值的时候,之间的文件就会自动删除;
optimize table tb_merge_tree ;
2.2ReplacingMergeTree引擎
这个引擎是在 MergeTree 的基础上,添加了“处理重复数据”的功能,该引擎和MergeTree的不同之处在于它会删除具有相同主键的重复项。数据的去重只会在合并的过程中出现。合并会在未知的时间在后台进行,所以你无法预先作出计划。有一些数据可能仍未被处理。因此,ReplacingMergeTree 适用于在后台清除重复的数据以节省空间,但是它不保证没有重复的数据出现。
特点:
在数据合并的时候 根据主键分区内自动的去重主键重复的数据,我们可以指定一个字段作为数据的版本,当去除重复数据的时候保留版本大的数据!
CH内部会自动的合并数据并去重重复数据 ,当然我们也可以手动的执行合并,但是每次处罚命令只能合并一个分区的数据,一般情况下等待他自己合并数据即可! 所以我们无法保证表中不存在重复主键数据
建表:
create table tb_rep_merge_tree(
id Int8 ,
name String ,
ctime Date ,
version UInt8
)
engine=ReplacingMergeTree(version) --这里面的参数,指得是版本数:ReplacingMergeTree引擎在合并的时候会自动的去重,并且只保留指定字段的最大版本数
order by id
partition by name
插入数据:
insert into tb_rep_merge_tree values (1, 'a','2020-08-05', 20);
insert into tb_rep_merge_tree values (1, 'b','2020-08-05', 30);
insert into tb_rep_merge_tree values (1, 'a','2020-08-05', 20);
insert into tb_rep_merge_tree values (1, 'a','2020-08-05', 30);
insert into tb_rep_merge_tree values (1, 'b','2020-08-05', 10);
查看结果:
手动合并分区 因为每次合并只能合并两个文件,所以手动执行两次:
optimize table tb_rep_merge_tree ;
结果:
分析:从以上结果可以看出,在合并的过程中,会删除主键重复的数据,只保留一个指定字段为数据版本的最大版本数据;
2.3CollapsingMergeTree 引擎
ClickHouse实现了CollapsingMergeTree来消除ReplacingMergeTree的限制(只删除小版本字段,只保留最大版本数据)。该引擎要求在建表语句中指定一个标记列Sign,后台Compaction时会将主键相同、Sign相反的行进行折叠,也即删除。
CollapsingMergeTree将行按照Sign的值分为两类:Sign=1的行称之为状态行,Sign=-1的行称之为取消行。
每次需要新增状态时,写入一行状态行;需要删除状态时,则写入一行取消行。在后台Compaction时,状态行与取消行会自动做折叠(删除)处理。而尚未进行Compaction的数据,状态行与取消行同时存在。
因此为了能够达到主键折叠(删除)的目的,需要业务层进行适当改造:
1) 执行删除操作需要写入取消行,而取消行中需要包含与原始状态行一样的数据(Sign列除外)。所以在应用层需要记录原始状态行的值,或者在执行删除操作前先查询数据库获取原始状态行;
2)由于后台Compaction时机无法预测,在发起查询时,状态行和取消行可能尚未被折叠;另外,ClickHouse无法保证primary key相同的行落在同一个节点上,不在同一节点上的数据无法折叠。因此在进行count(*)、sum(col)等聚合计算时,可能会存在数据冗余的情况。为了获得正确结果,业务层需要改写SQL,将count()、sum(col)分别改写为sum(Sign)、sum(col * Sign)。
CollapsingMergeTree虽然解决了主键相同的数据即时删除的问题
实例:
创建表:
create table tb_c_mt(
UserID UInt64,
PageViews UInt8,
Duration UInt8,
Sign Int8
)
engine=CollapsingMergeTree(Sign) --这个参数值得是标记字段
order by UserID;
插入数据:
--入状态行 数据
INSERT INTO tb_c_mt VALUES (4324182021466249495, 5, 146, 1);
INSERT INTO tb_c_mt VALUES (4324182021466249495, 5, 146, 1);
--后插入取消行数据
INSERT INTO tb_c_mt VALUES (4324182021466249495, 5, 146, -1);
执行:select * from tb_c_mt;
合并之后的数据:optimize table tb_c_mt;
查询的结果,说明我们查询的结果就是将标记为-1 的这行数据的上一行数据删除,
注意:
CollapsingMergeTree虽然解决了主键相同的数据即时删除的问题,但是状态持续变化且多线程并行写入情况下,状态行与取消行位置可能乱序,导致无法正常折叠。只有保证老的状态行在在取消行的上面, 新的状态行在取消行的下面! 但是多线程无法保证写的顺序!
2.4 VersionedCollapsingMergeTree
取消字段和数据版本同事使用,避免取消行数据无法删除的问题
为了解决CollapsingMergeTree乱序写入情况下无法正常折叠问题,VersionedCollapsingMergeTree表引擎在建表语句中新增了一列Version,用于在乱序情况下记录状态行与取消行的对应关系。主键相同,且Version相同、Sign相反的行,在Compaction时会被删除。
与CollapsingMergeTree类似, 为了获得正确结果,业务层需要改写SQL,将count()、sum(col)分别改写为sum(Sign)、sum(col * Sign)。
实例:
创建表以及插入数据:
//VersionedCollapsingMergeTree
create table tb_v_c_mt(
uid Int64,
name String,
sign Int8,
version Int8
)
engine=VersionedCollapsingMergeTree(sign,version) --参数值得是标记字段和版本字段
order by uid;
insert into tb_v_c_mt values(1001,'zss',-1,1);
insert into tb_v_c_mt values(1002,'zss',1,4);
insert into tb_v_c_mt values(1001,'zss',1,3);
insert into tb_v_c_mt values(1001,'zss',1,2);
insert into tb_v_c_mt values(1001,'zss',1,1);
结果展示:
结果分析:
VersionedCollapsingMergeTree表引擎解决了CollapsingMergeTree乱序写入情况下无法正常折叠问题,在建表语句中新增了一列Version,用于在乱序情况下记录状态行与取消行的对应关系。主键相同,且Version相同、Sign相反的行,在Compaction时会被删除。