持续的具体化视图查询

如需创建 Bigtable 表的持续具体化视图,请运行定义该持续具体化视图的 SQL 查询。

本文档介绍了相关概念和模式,可帮助您准备持续的具体化视图 SQL 查询。在阅读本文档之前,您应该先熟悉持续具体化视图GoogleSQL for Bigtable

持续的物化视图使用受限 SQL 语法。以下模式展示了如何构建持续的具体化视图 SQL 查询:

SELECT
  expression AS alias [, ...]
FROM from_item
[ WHERE bool_expression ]
GROUP BY expression [, ...];

from_item:
    {
      table_name [ as_alias ]
      | field_path
      }

as_alias:
    [ AS ] alias

如果您想将持续具体化视图 SQL 查询构建为异步辅助索引,请使用 ORDER BY 子句:

SELECT
  expression AS alias [, ...]
FROM from_item
[ WHERE bool_expression ]
ORDER BY expression [, ...];

from_item:
    {
      table_name [ as_alias ]
      | field_path
      }

as_alias:
    [ AS ] alias

查询限制

用于创建持续具体化视图的 SQL 查询必须遵循以下规则:

  • 必须是 SELECT 语句。
  • 必须包含 GROUP BY 子句,或者对于异步二级索引查询,必须包含 ORDER BY 子句,但不能同时包含这两个子句。
  • 必须仅使用受支持的聚合函数。
  • 每个组可以有多个聚合。

支持的汇总

您可以在定义持续具体化视图的 SQL 查询中使用以下聚合函数:

  • COUNT
  • SUM
  • MIN
  • MAX
  • HLL_COUNT.INIT
  • HLL_COUNT.MERGE
  • HLL_COUNT.MERGE_PARTIAL
  • ANY_VALUE
  • BIT_AND
  • BIT_OR
  • BIT_XOR
  • AVG

如果您指定了 SELECT COUNT(*),则必须定义行键,如以下示例所示:

SELECT
  '*' AS _key,
  COUNT(*) AS count
FROM
  foo
GROUP BY
  _key;

不支持的 SQL 功能

您无法使用以下 SQL 功能:

  • GoogleSQL for Bigtable 不支持的任何功能
  • ARRAY
  • ARRAY_AGG
  • ARRAY_CONCAT_AGG
  • COUNT_IF
  • CURRENT_TIME 和其他非确定性函数
  • DATEDATETIME 作为输出列(使用 TIMESTAMP 或存储字符串)。
  • 输出中的 DESC 排序
  • DISTINCT 选项,如 SUM(*DISTINCT* value) 中所示)
  • LIMIT/OFFSET
  • SELECT *
  • OVER 子句,用于创建窗口聚合
  • STRUCT

您也无法嵌套 GROUP BYORDER BY 子句,也无法创建地图列。如需了解其他限制,请参阅限制

避免排除的行

在以下情况下,输入行会被排除在连续的具体化视图之外:

  • 从行中选择的数据超过 1 MiB。例如,如果您的查询是 SELECT apple AS apples , SUM(banana) AS sum_bananas FROM my_table GROUP BY apples,则在 applebanana 列中包含超过 1 MiB 数据的任何行都会从持续具体化视图中排除。
  • 从相应行输出的数据超过 1 MiB。当您使用 SELECT REPEAT(apple, 1000) 等查询或使用大型常量时,可能会发生这种情况。
  • 输出的数据量比所选的数据量多 10 倍以上。
  • 查询与您的数据不匹配。这包括尝试除以零、整数溢出,或预期使用并非在每个行键中都使用的行键格式。

排除的行在首次处理时会增加用户错误指标。 如需详细了解可帮助您监控持续具体化视图的指标,请参阅指标

查询详情

本部分介绍了持续具体化视图查询,以及查询该视图时结果的可能外观。源表中的数据是输入,持续具体化视图中的结果数据是输出。输出数据是汇总数据或未汇总数据(在定义的键中)。

SELECT 语句

SELECT 语句用于配置持续具体化视图中使用的列和聚合。该语句必须使用 GROUP BY 子句跨行进行聚合,或者使用 ORDER BY 子句创建异步二级索引。

不支持 SELECT *,但支持 SELECT COUNT(*)

与典型的 SELECT 语句一样,您可以针对分组后的数据集进行多次聚合。未分组的列必须是汇总结果。

以下是一个标准 GROUP BY SQL 汇总查询示例:

SELECT
  myfamily["node"] AS node,
  myfamily["type"] AS type,
  COUNT(clicks) AS clicks_per_key
FROM
  mytable
GROUP BY
  node,
  type

行键和未汇总的数据

您可以指定 _key 作为持续具体化视图的行键。否则,GROUP BY 子句中的列将构成视图中的键。

_key 列定义的行键

在定义连续具体化视图时,您可以选择指定 _key 列。(这与您对 Bigtable 表执行 SQL 查询时获得的 _key不同。)如果您指定了 _key,则需遵守以下规则:

  • 您必须按 _key 分组,并且不能按任何其他内容分组,但可以(选择性地)按 _timestamp 分组。如需了解详情,请参阅时间戳
  • _key 列的类型必须为 BYTES

如果您计划使用 ReadRows 而不是 SQL 读取视图,指定 _key 会很有用,因为这样您可以控制行键格式。另一方面,对具有已定义 _key 的视图的 SQL 查询可能需要显式解码 _key,而不仅仅是返回结构化键列。

GROUP BYORDER BY 子句定义的行键

如果您未指定 _key,则 SELECT 列表中的非汇总列将成为视图中的行键。您可以为键列分配 SQL 惯例支持的任何名称。如果您打算使用 SQL 查询视图,而不是使用 ReadRows 请求,请使用此方法。

SELECT 列表中的非聚合输出列必须包含在 GROUP BY 子句中。在 GROUP BY 子句中写入列的顺序就是数据存储在连续具体化视图行键中的顺序。例如,GROUP BY a, b, c 隐式表示 ORDER BY a ASC, b ASC, c ASC

如果您使用 ORDER BY 子句而不是 GROUP BY 子句来创建异步二级索引,则 ORDER BY 子句中 SELECT 列表内的列会成为视图中的行键。在 ORDER BY 子句中写入列的顺序就是数据在连续具体化视图行键中的存储顺序。例如,ORDER BY a, b, c 会存储行键按 a ASCb ASCc ASC 排序的数据。

您的 SQL 过滤条件必须消除可能导致错误的潜在 NULL 或其他无效值。无效的行(例如包含 NULL 键列的行)会从结果中省略,并计入 materialized_view/user_errors 指标。如需调试用户错误,请尝试在持续具体化视图之外运行 SQL 查询。

汇总数据

查询中的聚合列用于定义生成持续具体化视图中数据的计算。

在持续具体化视图中,汇总列的别名会被视为列限定符。

请参考以下示例:

SELECT
  fam["baz"] AS baz,
  SUM(fam["foo"]) AS sum_foo,
  SUM(fam["bar"]) AS sum_bar
FROM
  TABLE

GROUP BY
  baz;

查询输出具有以下特征:

  • 每个 baz 的输出都位于单独的一行中,并按 baz ASC 顺序排列。
  • 如果给定的 baz 至少有一个 foo,则输出行的 sum_foo 为非 NULL 值。
  • 如果给定的 baz 至少有一个 bar,则输出行的 sum_bar 为非 NULL 值。
  • 如果给定的 baz 在任一列中都没有值,则会从结果中省略。

然后,如果您使用 SELECT * 查询视图,结果将类似于以下内容:

baz sum_foo sum_bar
baz1 sum_foo1 sum_bar1
baz2 sum_foo2 sum_bar2

时间戳

持续具体化视图中输出单元格的默认时间戳为 0 (1970-01-01 00:00:00Z)。当您使用 ReadRows 读取视图时,此时间戳可见;当您使用 SQL 查询视图时,此时间戳不可见。

如需在输出中使用其他时间戳,您可以向查询的 SELECT 列表添加一个 TIMESTAMP 类型的列,并将其命名为 _timestamp。如果您使用 ReadRows 查询持续具体化视图,_timestamp 将成为相应行中其他单元格的时间戳。

时间戳不得为 NULL,必须大于或等于零,并且必须是 1,000 的倍数(精确到毫秒)。Bigtable 不支持早于 Unix 纪元 (1970-01-01T00:00:00Z) 的单元格时间戳。

请看以下示例,该示例按天对汇总数据进行重采样。该查询使用 UNPACK 函数。

SELECT
  _key,
  TIMESTAMP_TRUNC(_timestamp, DAY) AS _timestamp,
  SUM(sum_family["sum_column"]) AS sum_column,
  SUM(sum_family["foo"]) AS second_sum_column
FROM
  UNPACK(
  SELECT
    *
  FROM
    my_table(with_history => TRUE))
GROUP BY
  1,
  2

如果给定的 SUM 在给定日期有非空输入,则输出行包含一个时间戳与截断的日期相匹配的汇总值。

如果您使用 SELECT * 查询视图,结果将类似于以下内容:

_key _timestamp sum_column second_sum_column
1 2024-05-01 00:00:00Z 23 99
2 2024-05-02 00:00:00Z 45 201
3 2024-05-03 00:00:00Z NULL 56
4 2024-05-04 00:00:00Z 8 NULL

编码

如果您使用 SQL 查询持续的具体化视图,则无需了解聚合值的编码方式,因为 SQL 会将结果显示为类型化列。

如果您使用 ReadRows 从视图中读取数据,则需要在读取请求中解码汇总数据。如需详细了解 ReadRows 请求,请参阅读取

连续具体化视图中的汇总值会根据视图定义中列的输出类型,使用下表中描述的编码进行存储。

类型 编码
布尔值 1 字节值,1 = true,0 = false
BYTES 无编码
INT64(或 INT、SMALLINT、INTEGER、BIGINT、TINYINT、BYTEINT) 64 位大端字节序
FLOAT64 64 位 IEEE 754,不包括 NaN 和 +/-inf
STRING UTF-8
时间/时间戳 64 位整数,表示自 Unix 纪元以来的微秒数(与 GoogleSQL 一致)
如需了解详情,请参阅 Data API 参考文档中的 编码

后续步骤