【发布时间】:2020-09-03 01:58:57
【问题描述】:
我在几个表中有String列uin,我如何才能有效地加入uin这些表?
在 Vertica 数据库中,我们使用 hash(uin) 将字符串列转换为具有 Int 数据类型的哈希 - 它显着提高了连接效率 - 你能推荐这样的东西吗?我试过CRC32(s),但它似乎工作错了。
【问题讨论】:
-
太过分了。 CH 在内部使用散列进行连接
标签: clickhouse
我在几个表中有String列uin,我如何才能有效地加入uin这些表?
在 Vertica 数据库中,我们使用 hash(uin) 将字符串列转换为具有 Int 数据类型的哈希 - 它显着提高了连接效率 - 你能推荐这样的东西吗?我试过CRC32(s),但它似乎工作错了。
【问题讨论】:
标签: clickhouse
此时,CH 不能很好地处理多连接查询(DB 星型模式),并且查询优化器还不足以完全依赖它。
所以它需要明确说明如何通过使用子查询而不是连接来“执行”查询。
让我们模拟您的查询:
SELECT table_01.number AS r
FROM numbers(87654321) AS table_01
INNER JOIN numbers(7654321) AS table_02 ON (table_01.number = table_02.number)
INNER JOIN numbers(654321) AS table_03 ON (table_02.number = table_03.number)
INNER JOIN numbers(54321) AS table_04 ON (table_03.number = table_04.number)
ORDER BY r DESC
LIMIT 8;
/*
┌─────r─┐
│ 54320 │
│ 54319 │
│ 54318 │
│ 54317 │
│ 54316 │
│ 54315 │
│ 54314 │
│ 54313 │
└───────┘
8 rows in set. Elapsed: 4.244 sec. Processed 96.06 million rows, 768.52 MB (22.64 million rows/s., 181.10 MB/s.)
*/
在我的电脑上大约需要 4 秒。让我们使用子查询重写它以显着加快速度。
SELECT number AS r
FROM numbers(87654321)
WHERE number IN (
SELECT number
FROM numbers(7654321)
WHERE number IN (
SELECT number
FROM numbers(654321)
WHERE number IN (
SELECT number
FROM numbers(54321)
)
)
)
ORDER BY r DESC
LIMIT 8;
/*
┌─────r─┐
│ 54320 │
│ 54319 │
│ 54318 │
│ 54317 │
│ 54316 │
│ 54315 │
│ 54314 │
│ 54313 │
└───────┘
8 rows in set. Elapsed: 0.411 sec. Processed 96.06 million rows, 768.52 MB (233.50 million rows/s., 1.87 GB/s.)
*/
还有其他方法可以优化JOIN:
使用External dictionary 摆脱“小”表上的连接
使用Join表引擎
使用ANY-strictness
使用特定设置,如 join_algorithm、partial_merge_join_optimizations 等
一些有用的参考:
Altinity webinar: Tips and tricks every ClickHouse user should know
Altinity webinar: Secrets of ClickHouse Query Performance
答案更新:
为了减少字符串列的存储消耗,请考虑将列类型更改为 LowCardinality (link 2),这会显着减小包含许多重复元素的列的大小。
使用此查询获取列的大小:
SELECT
name AS column_name,
formatReadableSize(data_compressed_bytes) AS data_size,
formatReadableSize(marks_bytes) AS index_size,
type,
compression_codec
FROM system.columns
WHERE database = 'db_name' AND table = 'table_name'
ORDER BY data_compressed_bytes DESC
要获得字符串的数字表示,需要使用hash-functions 之一。
SELECT 'jsfhuhsdf', xxHash32('jsfhuhsdf'), cityHash64('jsfhuhsdf');
【讨论】: