在这一部分中,我将介绍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;
那是因为Clickhouse在合并零件时执行替换过程,而零件在后台上不同步发生,而不是立即发生。要立即查看最终结果,您可以使用FINAL
修饰符:
SELECT * from inventory FINAL WHERE id=23;
注意:您可以在定义表相应地替换行时指定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);
现在更新该行:
INSERT INTO inventory VALUES (23, 'success', '1000', 'Confirmed', -1), (23, 'success', '2000', 'Cancelled', 1);
查看结果:
SELECT * FROM inventory;
立即查看最终结果:
SELECT * FROM inventory FINAL;
用法
崩溃的合并树可以以更控制的方式处理更新和删除。例如,您可以通过使用sign=-1
插入同一行和使用sign=1
的新排序键来更新各种键。该引擎有两个挑战:
-
由于您需要使用
sign=1
插入旧行,因此您需要通过从数据库或其他数据存储中获取来查询它。 -
如果偶然或故意插入多行,
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;
用法
此引擎通过以书面时间计算来帮助您减少沉重,固定分析查询的响应时间。在查询时间也将减少数据库负载。
原木家庭
具有最小功能的轻型发动机。当您需要快速编写许多小桌子(最多约100万行)并稍后阅读时,它们是最有效的。此外,这个家庭没有索引。但是,Log
和StripeLog
引擎可以将数据分解为多个块,以在读取数据时支持多线程。
我只会研究 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等。
。重要的是要注意,为用例选择合适的引擎可以显着提高性能和效率。因此,值得花时间了解每个引擎的优势和局限性,并选择最满足您需求的发动机。