持续的具体化视图查询
如需创建 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
和其他非确定性函数DATE
、DATETIME
作为输出列(使用TIMESTAMP
或存储字符串)。- 输出中的
DESC
排序 DISTINCT
选项,如SUM(*DISTINCT* value)
中所示)LIMIT/OFFSET
SELECT *
OVER
子句,用于创建窗口聚合STRUCT
您也无法嵌套 GROUP BY
或 ORDER BY
子句,也无法创建地图列。如需了解其他限制,请参阅限制。
避免排除的行
在以下情况下,输入行会被排除在连续的具体化视图之外:
- 从行中选择的数据超过 1 MiB。例如,如果您的查询是
SELECT apple AS apples , SUM(banana) AS sum_bananas FROM my_table GROUP BY apples
,则在apple
和banana
列中包含超过 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 BY
或 ORDER 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 ASC
、b ASC
、c 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 一致) |