Clickhouse表引擎—日志系列引擎

文章目录

  • ​​日志系列引擎​​
  • ​​日志引擎的特性​​
  • ​​共同点​​
  • ​​不同点​​
  • ​​TinyLog 引擎​​
  • ​​示例​​
  • ​​StripeLog 引擎​​
  • ​​示例​​
  • ​​Log 引擎​​
  • ​​示例​​
  • ​​总结​​

日志系列引擎

这些引擎是为了需要写入许多小数据量(少于一百万行)的表的场景而开发的。

这系列的引擎有:

  • StripeLog
  • Log
  • TinyLog

日志引擎的特性

共同点

  • 数据存储在磁盘上。
  • 写入时将数据追加在文件末尾。
  • 不支持突变操作。
  • 不支持索引。这意味着​​SELECT​​ 在范围查询时效率不高。
  • 非原子地写入数据。 如果某些事情破坏了写操作,例如服务器的异常关闭,你将会得到一张包含了损坏数据的表。

不同点

​Log​​​ 和 ​​StripeLog​​ 引擎支持:

并发写入数据。

​INSERT​​ 请求执行过程中表会被定,并且其他的读写数据的请求都会等待直到锁定被解除。如果没有写数据的请求,任意数量的读请求都可以并发执行。

并行读取数据。

在读取数据时,ClickHouse 使用多线程。 每个线程处理不同的数据块

​Log​​​ 引擎为表中的每一列使用不同的文件。​​StripeLog​​​ 将所有的数据存储在一个文件中。因此 ​​StripeLog​​​ 引擎在操作系统中使用更少的描述符,但是 ​​Log​​ 引擎提供更高的读性能。

​TinyLog​​​ 引擎是该系列中最简单的引擎并且提供了最少的功能和最低的性能。​​TinyLog​​ 引擎不支持并行读取和并发写入数据,并将每一列存储在不同的文件中。它比其余两种支持并行读取的引擎的读取速度更慢,并且使用了和 ​​Log​​ 引擎同样多的描述符。你可以在简单的低负载的情景下使用它。

TinyLog 引擎

最简单的表引擎,用于将数据存储在磁盘上。每列都存储在单独的压缩文件中。写入时,数据将附加到文件末尾。

并发数据访问不受任何限制:

  • 如果同时从表中读取并在不同的查询中写入,则读取操作将抛出异常
  • 如果同时写入多个查询中的表,则数据将被破坏。

这种表引擎的典型用法是 write-once:首先只写入一次数据,然后根据需要多次读取。查询在单个流中执行。换句话说,此引擎适用于相对较小的表(建议最多1,000,000行)。如果您有许多小表,则使用此表引擎是适合的,因为它比Log引擎更简单(需要打开的文件更少)。当您拥有大量小表时,可能会导致性能低下,但在可能已经在其它 DBMS 时使用过,则您可能会发现切换使用 TinyLog 类型的表更容易。不支持索引

在 Yandex.Metrica 中,TinyLog 表用于小批量处理的中间数据。

示例

创建表

CREATE TABLE test_tbl_tinylog
(
timestamp DateTime,
message_type String,
message String
)
ENGINE = TinyLog

插入数据

INSERT INTO test_tbl_tinylog VALUES (now(),'REGULAR','The first regular message');
INSERT INTO test_tbl_tinylog VALUES (now(),'REGULAR','The second regular message');
INSERT INTO test_tbl_tinylog VALUES (now(),'WARNING','The first warning message');

查询数据​​ select * from test_tbl_tinylog;​

┌───────────timestamp─┬─message_type─┬─message────────────────────┐
│ 2022-09-15 07:49:21 │ REGULAR │ The first regular message │
│ 2022-09-15 07:49:22 │ REGULAR │ The second regular message │
│ 2022-09-15 07:49:23 │ WARNING │ The first warning message │
└─────────────────────┴──────────────┴────────────────────────────┘

从这里就可以看出数据存在在一个data part 里面,所以也没有办法很好的并发,而且数据文件里面没有mark 文件

而且每列都有自己的.bin文件

StripeLog 引擎

该引擎属于日志引擎系列,在你需要写入许多小数据量(小于一百万行)的表的场景下使用这个引擎。

​StripeLog​​​ 引擎将所有列存储在一个文件中。对每一次 ​​Insert​​ 请求,ClickHouse数据块追加在表文件的末尾,逐列写入。

ClickHouse 为每张表写入以下文件:

  • ​data.bin​​ — 数据文件。
  • ​index.mrk​​ — 带标记的文件。标记包含了已插入的每个数据块中每列的偏移量。

​StripeLog​​​ 引擎不支持 ​​ALTER UPDATE​​​ 和 ​​ALTER DELETE​​ 操作。

带标记的文件使得 ClickHouse 可以并行的读取数据。这意味着 ​​SELECT​​​ 请求返回行的顺序是不可预测的。使用 ​​ORDER BY​​ 子句对行进行排序

示例

建表

CREATE TABLE test_tbl_stripe_log
(
timestamp DateTime,
message_type String,
message String
)
ENGINE = StripeLog

插入数据:

INSERT INTO test_tbl_stripe_log VALUES (now(),'REGULAR','The first regular message')
INSERT INTO test_tbl_stripe_log VALUES (now(),'REGULAR','The second regular message'),(now(),'WARNING','The first warning message')

我们使用两次 ​​INSERT​​​ 请求从而在 ​​data.bin​​ 文件中创建两个数据块。

ClickHouse 在查询数据时使用多线程。每个线程读取单独的数据块并在完成后独立的返回结果行。这样的结果是,大多数情况下,输出中块的顺序和输入时相应块的顺序是不。

SELECT * FROM test_tbl_stripe_log

查询结果,很明显和我们的插入顺序不一致

┌───────────timestamp─┬─message_type─┬─message────────────────────┐
│ 2022-09-15 07:17:48 │ REGULAR │ The second regular message │
│ 2022-09-15 07:17:48 │ WARNING │ The first warning message │
└─────────────────────┴──────────────┴────────────────────────────┘
┌───────────timestamp─┬─message_type─┬─message───────────────────┐
│ 2022-09-15 07:17:46 │ REGULAR │ The first regular message │
└─────────────────────┴──────────────┴───────────────────────────┘

这个时候我们可以对数据进行排序

SELECT * FROM test_tbl_stripe_log order by timestamp;
┌───────────timestamp─┬─message_type─┬─message───────────────────┐
│ 2022-09-15 07:17:46 │ REGULAR │ The first regular message │
└─────────────────────┴──────────────┴───────────────────────────┘
┌───────────timestamp─┬─message_type─┬─message────────────────────┐
│ 2022-09-15 07:17:48 │ REGULAR │ The second regular message │
│ 2022-09-15 07:17:48 │ WARNING │ The first warning message │
└─────────────────────┴──────────────┴────────────────────────────┘

我们看一下数据目录

Clickhouse表引擎—日志系列引擎

由于我们是用docker部署的,所以我们进入到容器目录下面,我们发现只有一个​​data.bin​​ 文件,也就是所有的列都放在一起

Clickhouse表引擎—日志系列引擎

Log 引擎

​Log​​​ 与 ​​TinyLog​​ 的不同之处在于,mark文件与列文件存在一起。这些标记写在每个数据块上,并且包含偏移量,这些偏移量指示从哪里开始读取文件以便跳过指定的行数。这使得可以在多个线程中读取表数据。对于并发数据访问,可以同时执行读取操作,而写入操作则阻塞读取和其它写入。

​Log​​​引擎不支持索引。同样,如果写入表失败,则该表将被破坏,并且从该表读取将返回错误。​​Log​​引擎适用于临时数据,write-once 表以及测试或演示目的。

示例

建表

CREATE TABLE test_tbl_log
(
timestamp DateTime,
message_type String,
message String
)
ENGINE = Log

插入数据

INSERT INTO test_tbl_log VALUES (now(),'REGULAR','The first regular message');
INSERT INTO test_tbl_log VALUES (now(),'REGULAR','The second regular message');
INSERT INTO test_tbl_log VALUES (now(),'WARNING','The first warning message');

查询​​select * from test_tbl_log;​

┌───────────timestamp─┬─message_type─┬─message────────────────────┐
│ 2022-09-15 07:39:30 │ REGULAR │ The second regular message │
└─────────────────────┴──────────────┴────────────────────────────┘
┌───────────timestamp─┬─message_type─┬─message───────────────────┐
│ 2022-09-15 07:39:26 │ REGULAR │ The first regular message │
└─────────────────────┴──────────────┴───────────────────────────┘
┌───────────timestamp─┬─message_type─┬─message───────────────────┐
│ 2022-09-15 07:39:31 │ WARNING │ The first warning message │
└─────────────────────┴──────────────┴───────────────────────────┘

我们查看数据目录,发现有三个​​.bin​​ 文件,也就是每一列使用不同的文件

Clickhouse表引擎—日志系列引擎

总结

日志系列引擎一般用的不多,使用场景主要是中间表数据

日志引擎

是否支持并发

数据文件是否按列划分文件

是否有Mark

Log

TinyLog

StripeLog