为什么 clickhouse 无法快速合并主键上已排序的两个表?

问题描述 投票:0回答:1

我有两个巨大的表,有 20 亿行:

CREATE TABLE transactions (
    `id` UInt64,
    `from_address` String,
    `date` UInt64,
)
ENGINE = MergeTree
PRIMARY KEY from_address
ORDER BY from_address
SETTINGS index_granularity = 8192

和 3800 亿行

CREATE TABLE addresses_tmp (
    `id` UInt64,
    `address` String
)
ENGINE = MergeTree
PRIMARY KEY address
ORDER BY address
SETTINGS index_granularity = 8192

我需要对 from_address 和 address 字段(主键字段)执行简单的联接。 Clickhouse 能够从这些表中进行选择,并按这些列排序,速度非常快,不到一分钟,对于如此大的 JOIN 来说,这对我来说是可以接受的。根据 clickhouse 日志,这两个查询在峰值时消耗的内存都低于 100M:

SELECT sum(id) FROM (SELECT * FROM addresses ORDER BY address)
SELECT sum(id) FROM (SELECT * FROM transactions ORDER BY from_address)

现在我尝试执行连接本身:

CREATE TABLE transactions_tmp
ENGINE = MergeTree
PRIMARY KEY id
AS SELECT
    t.id AS to_id,
    tx.date,
    tx.id
FROM transactions AS tx
INNER JOIN addresses AS t ON t.address = tx.to_address

通过同时迭代这些表来连接这些表似乎是微不足道的,事实上,clickhouse 总是失败并出现这样的错误(我尝试了默认合并算法和 full_sorting_merge):

超出内存限制(总计):将使用 28.05 GiB(尝试 分配 4342112 字节的块,最大:27.86 GiB。 OvercommitTracker 决策:选择查询停止 过度使用跟踪器。

或者,如果我使用 SETTINGS join_algorithm = 'partial_merge' 它不会失败,但会卡在 15% 左右,连接速度会降低到每秒 30K 行左右,因此需要几天时间才能完成。那么我如何强制 Clickhouse 对排序数据执行简单的合并连接?

join out-of-memory clickhouse array-merge
1个回答
0
投票

由于使用默认的“哈希”算法,您的 JOIN() 需要太多内存,因此您需要使用限制内存使用的替代连接算法之一。我建议尝试 Grace_hash 算法:

https://clickhouse.com/docs/en/operations/settings/settings#join_algorithm

SETTINGS join_algorithm = 'grace_hash'
© www.soinside.com 2019 - 2024. All rights reserved.