我有一个表,里面有相同数据的几个版本。每个版本都可以通过一个时间戳字段来识别。
这是我想出的查询,使用一个窗口函数,只获取我的数据的最新版本。
WITH tbl AS (
SELECT
*,
first_value(`timestamp`) OVER (PARTITION BY concatenate ORDER BY `timestamp` DESC) AS latest
FROM
dataset.table as tbl
)
SELECT
*
FROM tbl
WHERE
`timestamp` = latest;
Concatenate是一个字段的组合,代表了我的行的唯一性。
这样做是可行的,但是,为了优化这个问题,我创建了一个分区表,如下图所示,以减少我的查询处理的数据量,因为数据的版本很多。
CREATE TABLE
`dataset.partitioned_table`
PARTITION BY
DATE(`timestamp`)
CLUSTER BY concatenate AS
SELECT * FROM `dataset.table`;
然而,当我在新的分区数据上运行查询时,BigQuery处理的数据量与非分区的数据量完全相同,它应该处理三分之一的数据(我正在用3个版本的数据进行测试)。
我的感觉是,窗口函数是在处理整个数据,在使用分区表时,可能有更好的方法来实现,然而,我还找不到如何做到这一点。
也试过按假的日期创建一个表分区,但按时间戳和联接字段进行聚类,但得到的结果是一样的。
你的查询每次都在读取整个表,因为它的编写方式。
请检查CTE(即 WITH
子句),它不受任何的 WHERE
子句来减少读取的数据量。
如果你想只读取表的最新分区,你将不得不做这样的事情。
WITH tbl AS (
SELECT
*,
first_value(`timestamp`) OVER (PARTITION BY concatenate ORDER BY `timestamp` DESC) AS latest
FROM
dataset.table as tbl
#### this is the super important bit to reduce your reads ####
WHERE DATE(timestamp) >= DATE('whatever_you_think_your_last_few_partitions_should_be')
)
SELECT
*
FROM tbl
WHERE
`timestamp` = latest;
基本上,你需要用 WHERE
以减少处理数据的数量。
请记住,我在查询中添加了 whatever_you_think_your_last_few_partitions_should_be
因为这真的取决于你是否要扫描最后X个数量的分区是否有重复,或1周的日期范围,或者也许只是字面上的最后一天。取决于你的解决方案。