【问题标题】:Clickhouse - join on string columnsClickhouse - 加入字符串列
【发布时间】:2020-09-03 01:58:57
【问题描述】:

我在几个表中有Stringuin,我如何才能有效地加入uin这些表?

在 Vertica 数据库中,我们使用 hash(uin) 将字符串列转换为具有 Int 数据类型的哈希 - 它显着提高了连接效率 - 你能推荐这样的东西吗?我试过CRC32(s),但它似乎工作错了。

【问题讨论】:

  • 太过分了。 CH 在内部使用散列进行连接

标签: clickhouse


【解决方案1】:

此时,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_algorithmpartial_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');

【讨论】:

  • 不完全是我问的,但非常感谢您提供有用的链接!问题不是关于 clickhouse 本身的连接优化,而是关于如何以数字表示形式转换字符串列。主要是我需要这个来减少存储空间。例如,我在列中有“jsfhuhsdf”,与整数相比,字符串是一个重数据。我想使用这个 id 将 raw 加入另一个表。我可以只使用字符串,但输出表比我在整数上连接时重 10 倍。我认为 CRC32 是一个很好的解决方案,我刚刚在查询中遇到错误,现在它运行良好
猜你喜欢
  • 2021-02-19
  • 1970-01-01
  • 2021-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
相关资源
最近更新 更多