我有一个 BigQuery 表,该表由
ts
字段 (TIMESTAMP) 分区,并由 tag
字段 (STRING) 集群。它还具有一些其他字段:speed
(FLOAT)和name
(STRING)
当我执行
SELECT * from table1
时,它会按预期预测全桌计费
当我执行
SELECT * from table1 WHERE ts='xxxxx'
时,它会按预期预测分区计费
当我执行
SELECT * from table1 WHERE tag='yyy'
时,它预测不到满桌计费(在我的例子中约为 50%)。查询后“字节计费”与预测相同。我预计查询后计费与查询前预测有所不同。
当我执行
SELECT * from table1 WHERE name='zzz'
时,它还预测不到全表计费(在我的例子中约为 1%),并且查询后“计费字节”与预测相同。我期待全表计费,因为我什至没有使用聚集字段作为过滤器
当我执行
SELECT * from table1 WHERE speed=5
时,它预测全表计费和查询后计费相同。 speed
和name
都是非集群的,但name
过滤会减少计费,而speed
则不会。我预计这两个领域都会有类似的行为。
当我执行
DELETE from table1 where tag='xxx'
时,我也会得到全桌计费。我只期待集群计费。
知道发生了什么事吗?似乎在大多数情况下,我的期望没有得到满足,所以我可能错过了一些东西..
分区和集群的区别在于分区将表划分为段,而集群将数据排序为块。 当您在分区表上添加 where 条件时,您将获得正确的估计账单,因为它会修剪表(基本上查看该段中的数据)。然而,通过集群,您的 BQ 在运行查询之前并不知道它将扫描多少个块,因此估计可能不准确。例如,在这种情况下,您将拥有基于
ts
(分区)的多个分段,并且在每个块中您将拥有集群块。
SELECT * from table1
时,它预测全表这是因为您没有指定BQ扫描表中的特定段,因此它将扫描整个表。您可以做的一件事是在分区列上强制要求 where 条件。
CREATE OR REPLACE TABLE
projectId.dataset.table
PARTITION BY
TIMESTAMP_TRUNC(timestamp, DAY)
OPTIONS( require_partition_filter=TRUE )
SELECT * from table1 WHERE ts='xxxxx'
时,它会预测
正如预期的那样分区计费这是因为您指定 BQ 扫描特定段而不是整个表。
当您对表执行 DELETE 操作时,通常会导致全表计费,因为 BQ 需要扫描整个表来识别符合 DELETE 条件的行,然后需要重写整个表来删除这些行。
SELECT * from table1 WHERE tag='yyy'
时,
预测不到满桌计费(在我的例子中约为 50%)。
查询后“字节计费”与预测相同。我曾是
期望查询后计费与查询前预测不同。集群降低了成本。文档称,通过聚类,您可能无法获得准确的估计,但 BQ 会尝试仅扫描相关部分,因此有时可能是准确的。
SELECT * from table1 WHERE name='zzz'
时,它也
预测不到满桌的账单(在我的例子中约为 1%),并且
同样,查询后“字节计费”与预测相同。我
期待全表计费,因为我什至没有使用集群
字段作为过滤器BQ 还有其他优化性能的方法,例如缓存。如果您运行类似的查询,BigQuery 可能会使用缓存的结果来减少扫描的数据量,而当您按速度过滤时,情况可能并非如此。