首页 > 解决方案 > Where 子句不适用于 ClickHouse 视图

问题描述

我正在尝试在源表上创建一个视图,然后从视图中选择特定时间戳范围的数据并将其放入目标表中。

我们有一个源表:

100 万行被推送到对应于 1 月 1 日至 1 月 31 日数据的源表。

    CREATE TABLE IF NOT EXISTS source(
      CELL          String,
      TIMESTAMP     DateTime,
      COUNTER1      Float32,
      COUNTER2      Float32,
      COUNTER3      Float32,
      COUNTER4      Float32,
      COUNTER5      Float32,
      COUNTER6      Float32,
      InsertionTime DateTime DEFAULT now(),      /* Insertion Time */
      QHour         DateTime DEFAULT toStartOfFifteenMinutes(TIMESTAMP)
    ) ENGINE=ReplacingMergeTree()
    PARTITION BY toYYYYMM(TIMESTAMP)
    ORDER BY (QHour, TIMESTAMP, CELL)
    SETTINGS index_granularity = 31768

现在,我们在源表上创建了一个视图。

    CREATE VIEW IF NOT EXISTS myView
      AS SELECT
        CELL,
        QHour,
        toStartOfFifteenMinutes(TIMESTAMP)      AS ViewQHour,
        100 * sum(COUNTER1) / sum(COUNTER2)     AS KPI1
      FROM ( 
        SELECT
            CELL,
            TIMESTAMP,
            any(QHour) as QHour
            argMax(COUNTER1, InsertionTime)     AS COUNTER1,
            argMax(COUNTER2, InsertionTime)     AS COUNTER2
        FROM ThreeGCell
        GROUP BY TIMESTAMP, CELL, QHour)
    GROUP BY ViewQHour, CELL
    ORDER BY ViewQHour, CELL

现在,在视图中,我需要从视图中选择一个时间段的数据:1 月 1 日至 1 月 10 日。

SELECT * 
FROM myView 
WHERE QHour >= toDateTime('2020-01-01 00:00:00') AND QHour <= toDateTime('2020-01-10 00:00:00')

但是视图上的选择查询会将所有 100 万行添加到目标表中,该表是整个 1 月的数据,而我正在寻找仅 1 月 1 日至 1 月 10 日的特定时期的数据。

我有以下问题:

  1. 我们可以修改视图上的查询以仅处理特定时间段吗?
  2. 我们可以动态生成源表中推送的最新数据集的视图吗?我的意思是我们只有源表中的过滤数据集并在视图中使用过滤后的数据?可以修改此类过滤器以使用不同的时间范围吗?例如,我们在视图中有从 1 月 1 日到 1 月 10 日的数据。然后在第二次运行中,我们在视图中有从 1 月 11 日到 1 月 20 日的数据。

标签: viewclickhouse

解决方案


CREATE VIEW IF NOT EXISTS myView
....
ORDER BY ViewQHour, CELL

ORDER BY不幸的是,大多数数据库都禁止使用 CH 创建视图。在最初的设计中允许创建这样的视图是一个错误。

ORDER BY取消谓词下推,因为它在某些情况下会破坏结果(优化器仍然很弱并且不理解 runningDiff() 和 neighbour() 的情况。

https://github.com/ClickHouse/ClickHouse/issues/9425#issuecomment-592658368


推荐阅读