Clickhouse基本教程:表引擎
#教程 #database #clickhouse

在这一部分中,我将介绍Clickhouse表引擎。与任何其他数据库一样,ClickHouse使用引擎来确定表的存储,复制和并发方法。每个引擎都有优点和缺点,您应该根据需要选择它们。此外,发动机分为分享主要功能的家庭。作为一篇实际的文章,我将深入研究每个家庭中最有用的文章,并让其他人引起您的兴趣。

现在,让我们从第一个也是最可用的家庭开始:

Merge-Tree家族

正如它所说的,当您想在Clickhouse中创建表格时,这是最可能的选择。它基于Log Structured Merge-Tree的数据结构。 LSM树针对写入密集的工作量进行了优化。它们旨在通过在内存中缓冲它们,然后定期将它们以分类顺序进行磁盘来处理大量写作。这允许更快地写入大量数据并减少磁盘碎片的可能性。它们被认为是B-Tree数据结构的替代方法,该数据结构在传统的关系数据库中很常见。

注意:对于此家族的所有引擎,您可以使用Replicated作为引擎名称的前缀来创建每个ClickHouse节点上表的复制。

现在让我们调查这个家庭中的普通引擎。

这是Merge-Tree DDL的示例:

CREATE TABLE inventory
(
    `id` Int32,
    `status` String,
    `price` String,
    `comment` String
)
ENGINE = MergeTree
PRIMARY KEY (id, price)
ORDER BY (id, price, status)

Merge-Tree表使用sparse indexing来优化查询。
简而言之,在稀疏索引中,数据分为多个部分。每个部分都用order by键(称为 sort键)对每个部分进行排序,其中第一个键在排序中具有最高优先级。然后,每个部分都被分解为称为颗粒的组,其主要密钥的第一个和最后一个项目被视为标记。由于这些标记是从排序数据中提取的,因此主键应为排序键的子集。然后,对于每个在主键上包含过滤器的查询,ClickHouse都会在这些标记上执行二进制搜索,以尽快找到目标颗粒。最后,ClickHouse在内存中加载目标颗粒并搜索匹配行。

注意:您可以省略DDL中的PRIMARY KEY,Clickhouse将将键视为主要键。

补充梅格特里

DDL

在此引擎中,带有均等键的行被最后一行取代。考虑以下引擎:

CREATE TABLE inventory
(
    `id` Int32,
    `status` String,
    `price` String,
    `comment` String
)
ENGINE = ReplacingMergeTree
PRIMARY KEY (id)
ORDER BY (id, status);

假设您在此表中插入一行:

INSERT INTO inventory VALUES (23, 'success', '1000', 'Confirmed');

现在让我们用相同的键插入另一行:

INSERT INTO inventory VALUES (23, 'success', '2000', 'Cancelled'); 

现在后一行将替换上一行。请注意,如果您获得选择行,则可能会面对两者:

SELECT * from inventory WHERE id=23;

Result of the replacing merge tree without Final modifier

那是因为Clickhouse在合并零件时执行替换过程,而零件在后台上不同步发生,而不是立即发生。要立即查看最终结果,您可以使用FINAL修饰符:

SELECT * from inventory FINAL WHERE id=23;

Result of the replacing merge tree with Final modifier

注意:您可以在定义表相应地替换行时指定column as version

用法

替换合并树被广泛用于重复数据删除。随着Clickhouse在频繁更新中的性能较差,您可以通过使用平等排序键插入新行来更新列,而Clickhouse将在后台删除停滞的行。更新排序键肯定是一项挑战,因为在这种情况下它不会删除旧行。在这种情况下,您可以使用折叠的合并树,在下一部分中解释。

Collapsingmergetree

在此引擎中,您可以定义一个符号列,并要求数据库使用sign=-1删除摊位行,并使用sign=1保持新行。

DDL

CREATE TABLE inventory
(
    `id` Int32,
    `status` String,
    `price` String,
    `comment` String,
    `sign` Int8
)
ENGINE = CollapsingMergeTree(sign)
PRIMARY KEY (id)
ORDER BY (id, status);

让我们在此表中插入一行:

INSERT INTO inventory VALUES (23, 'success', '1000', 'Confirmed', 1);

Data in Collapsing Merge Tree before update

现在更新该行:

INSERT INTO inventory VALUES (23, 'success', '1000', 'Confirmed', -1), (23, 'success', '2000', 'Cancelled', 1);

查看结果:

SELECT * FROM inventory;

Data in Collapsing Merge Tree after update without final modifier

立即查看最终结果:

SELECT * FROM inventory FINAL;

Data in Collapsing Merge Tree after update with final modifier

用法

崩溃的合并树可以以更控制的方式处理更新和删除。例如,您可以通过使用sign=-1插入同一行和使用sign=1的新排序键来更新各种键。该引擎有两个挑战:

  1. 由于您需要使用sign=1插入旧行,因此您需要通过从数据库或其他数据存储中获取来查询它。

  2. 如果偶然或故意插入多行,sign等于1或-1,则可能面临不必要的结果。这就是为什么您应该考虑所有情况解释的here

Gragingmergetree

使用此引擎,您可以将表的聚合物归为另一个。

DDL

考虑此库存表。我们需要每个项目ID的最高价格及其在另一个表中的项目数量。

CREATE TABLE inventory
 (
    `id` Int32,
    `status` String,
    `price` Int32,
    `num_items` UInt64
) ENGINE = MergeTree ORDER BY (id, status);  

现在,让我们通过汇总mergetree将其结果实现在另一个表中:

CREATE MATERIALIZED VIEW agg_inventory
(
    `id` Int32,
    `max_price` AggregateFunction(max, Int32),
    `sum_items` AggregateFunction(sum, UInt64)
)
ENGINE = AggregatingMergeTree() ORDER BY (id)
AS SELECT
    id,
    maxState(price) as max_price,
    sumState(num_items) as sum_items
FROM inventory2
GROUP BY id;

现在让我们插入其中并查看结果:

INSERT INTO inventory2 VALUES (3, 100, 2), (3, 500, 4);

SELECT id, maxMerge(max_price) AS max_price, sumMerge(sum_items) AS sum_items 
FROM agg_inventory WHERE id=3 GROUP BY id;

Output of aggregating merge tree

用法

此引擎通过以书面时间计算来帮助您减少沉重,固定分析查询的响应时间。在查询时间也将减少数据库负载。

原木家庭

具有最小功能的轻型发动机。当您需要快速编写许多小桌子(最多约100万行)并稍后阅读时,它们是最有效的。此外,这个家庭没有索引。但是,LogStripeLog引擎可以将数据分解为多个块,以在读取数据时支持多线程。

我只会研究 tinylog 引擎。要检查其他人,您可以访问this link

Tinylog

该表主要用作写入方法。也就是说,您将编写一次数据,并根据需要进行尽可能多的阅读。当Clickhouse在单个流中读取数据时,最好将表的大小保持在1M行中。

CREATE TABLE log_location
 (
    `id` Int32,
    `long` String,
    `lat` Int32
) ENGINE = TinyLog;

用法

您可以将此引擎用作批处理操作的中间状态。

整合家庭

该家族中的引擎被广泛用于与其他数据库和经纪人连接,并具有获取或插入数据的能力。

我将介绍MySQL和Kafka引擎,但是您可以研究其他here

mysql引擎

使用此引擎,您可以通过Clickhouse与MySQL数据库连接并读取其数据或插入行。

CREATE TABLE mysql_inventory
(
    `id` Int32,
    `price` Int32
)
ENGINE = MySQL('host:port', 'database', 'table', 'user', 'password')

卡夫卡引擎

使用此引擎,您可以连接到KAFKA群集,并使用定义的消费者组读取其数据。该引擎广泛用于CDC。

要了解有关此功能的更多信息,请阅读有关此主题的this文章。

结论

在本文中,我们看到了Clickhouse数据库中一些最重要的引擎。显然,Clickhouse提供了各种适合各种用例的发动机选项。合并树引擎是默认引擎,适用于大多数情况,但可以用其他引擎替换为ExtregatingMergetree,Tinylog等。

重要的是要注意,为用例选择合适的引擎可以显着提高性能和效率。因此,值得花时间了解每个引擎的优势和局限性,并选择最满足您需求的发动机。