【问题标题】:Clickhouse join with conditionClickhouse 加入条件
【发布时间】:2021-02-12 01:28:23
【问题描述】:

我发现了奇怪的东西,查询:

SELECT *
FROM progress as pp
ALL LEFT JOIN links as ll USING (viewId)
WHERE viewId = 'a776a2f2-16ad-448a-858d-891e68bec9a8' 

结果:0 rows in set. Elapsed: 5.267 sec. Processed 8.62 million rows, 484.94 MB (1.64 million rows/s., 92.08 MB/s.)

这里修改查询:

SELECT *
FROM
  (SELECT *
   FROM progress
   WHERE viewId = 'a776a2f2-16ad-448a-858d-891e68bec9a8') AS p ALL
LEFT JOIN
  (SELECT *
   FROM links
   WHERE viewId = toUUID('a776a2f2-16ad-448a-858d-891e68bec9a8')) AS l ON p.viewId = l.viewId;

结果:0 rows in set. Elapsed: 0.076 sec. Processed 4.48 million rows, 161.35 MB (58.69 million rows/s., 2.12 GB/s.)

但它看起来很脏。

不应该考虑where条件来优化查询吗?

在此处编写查询的正确方法是什么,如果它将在哪里呢?

然后我尝试添加另一个联接:

SELECT *
FROM
  (SELECT videoUuid AS contentUuid,
          viewId
   FROM
     (SELECT *
      FROM progress
      WHERE viewId = 'a776a2f2-16ad-448a-858d-891e68bec9a8') p ALL
   LEFT JOIN
     (SELECT *
      FROM links
      WHERE viewId = toUUID('a776a2f2-16ad-448a-858d-891e68bec9a8')) USING `viewId`) ALL
LEFT JOIN `metaInfo` USING `viewId`,
                           `contentUuid`;

考虑到我只想将 3 个表与条件选择一行连接起来,结果又很慢:

0 rows in set. Elapsed: 1.747 sec. Processed 9.13 million rows, 726.55 MB (5.22 million rows/s., 415.85 MB/s.)

【问题讨论】:

  • 哪个表包含viewId字段?请修正你的语法。之前你放了一个逗号
  • 固定逗号,两个表都包含viewId字段
  • 您是否忘记使用表的别名来限定 viewid:WHERE pp.viewId = 'a776a2f2-16ad-448a-858d-891e68bec9a8'
  • 我刚做了,速度一样。
  • 您的问题到底是什么?是关于查询的性能还是关于您没有得到任何结果?

标签: sql 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)
WHERE r = 54320
/*
┌─────r─┐
│ 54320 │
└───────┘

1 rows in set. Elapsed: 6.261 sec. Processed 96.06 million rows, 768.52 MB (15.34 million rows/s., 122.74 MB/s.)
*/

让我们使用子查询重写它以显着加快速度。

SELECT number AS r
FROM numbers(87654321)
WHERE r = 54320 AND number IN (
  SELECT number AS r
  FROM numbers(7654321)
  WHERE r = 54320 AND number IN (
    SELECT number AS r
    FROM numbers(654321)
    WHERE r = 54320 AND number IN (
      SELECT number AS r
      FROM numbers(54321)
      WHERE r = 54320
    )
  )
)
/*
┌─────r─┐
│ 54320 │
└───────┘

1 rows in set. Elapsed: 0.481 sec. Processed 96.06 million rows, 768.52 MB (199.69 million rows/s., 1.60 GB/s.)
*/

还有其他方法可以优化JOIN


一些有用的参考:

Altinity webinar: Tips and tricks every ClickHouse user should know

Altinity webinar: Secrets of ClickHouse Query Performance

【讨论】:

    【解决方案2】:

    不应该优化查询条件吗?

    尚未实施此类优化

    【讨论】:

      【解决方案3】:

      这是预期的行为。 根据 CH doc https://clickhouse.tech/docs/en/sql-reference/statements/select/join/#performance “运行 JOIN 时,相对于查询的其他阶段没有优化执行顺序。连接(在右表中的搜索)在 WHERE 过滤之前和聚合之前运行。”

      【讨论】:

        猜你喜欢
        • 2019-07-27
        • 2020-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-04
        • 2012-11-28
        • 2020-12-07
        • 1970-01-01
        相关资源
        最近更新 更多