使用BigQuery

时间:2018-03-02 21:40:05

标签: google-cloud-platform google-bigquery bigdata

我试图通过使用偏移量抓取某个行号来模拟BigQuery中的分页。看起来检索结果的时间会随着偏移量的增加而逐渐降低,直到遇到ResourcesExceeded错误。以下是一些示例查询:

enter image description here

是否有更好的方法来使用等效的"偏移"与BigQuery没有看到性能下降?我知道这可能要求一个不存在的魔法子弹,但是想知道是否有解决方法来实现上述目标。如果没有,如果有人可以提出另一种方法来获得上述方法(例如kinetica或cassandra或其他任何方法),那将非常感激。

3 个答案:

答案 0 :(得分:2)

BigQuery等系统的偏移通过读取和丢弃所有结果直到偏移来实现。

您需要使用列作为下限,以使引擎能够直接从键范围的那一部分开始,您不能让引擎在查询的中途随机搜索。

例如,假设您想通过费率代码,取件和下车时间查看出租车行程:

SELECT *
FROM [nyc-tlc:green.trips_2014]
ORDER BY rate_code ASC, pickup_datetime ASC, dropoff_datetime ASC
LIMIT 100

如果您通过OFFSET 100000执行此操作,则需要4秒,第一行是:

pickup_datetime: 2014-01-06 04:11:34.000 UTC
dropoff_datetime: 2014-01-06 04:15:54.000 UTC
rate_code: 1

如果不是偏移,我使用了那些日期和费率值,查询只需要2.9s:

SELECT *
FROM [nyc-tlc:green.trips_2014]
WHERE rate_code >= 1
  AND pickup_datetime >= "2014-01-06 04:11:34.000 UTC"
  AND dropoff_datetime >= "2014-01-06 04:15:54.000 UTC"
ORDER BY rate_code ASC, pickup_datetime ASC, dropoff_datetime ASC
limit 100

那是什么意思?然后,不是允许用户使用特定的结果#范围(例如,从100000开始的新行),而是以更自然的形式指定它(例如,2015年1月6日开始的骑行方式。

如果你想得到花哨,并且真的需要允许用户使用特定的实际行号,你可以通过提前计算行范围来提高效率,比如查询所有内容并记住开头的行号每天的小时数(8760个值),甚至几分钟(525600个值)。然后你可以用它来更好地猜测有效的开始。查找给定行范围内的最近日/分钟(例如,在Cloud Datastore中),然后将该用户查询转换为上述更高效的版本。

答案 1 :(得分:1)

正如Dan已经提到的,你需要引入一个行号。现在row_number() over ()超出了资源。这基本上意味着你必须分开计算行的工作:

  • 决定少数和尽可能均匀分布的分区
  • 计算每个分区的行数
  • 以后要知道何时开始计数行的分区的累积总和
  • 分开计算行的工作
  • 使用行计数列保存新表以供日后使用

作为分区,我使用EXTRACT(month FROM pickup_datetime),因为它很好地分发

WITH
  temp AS (
  SELECT
    *,
    -- cumulative sum of partition sizes so we know when to start counting rows here
    SUM(COALESCE(lagged,0)) OVER (ORDER BY month RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) cumulative
  FROM (
      -- lag partition sizes to next partition
    SELECT
      *,
      LAG(qty) OVER (ORDER BY month) lagged
    FROM (
        -- get partition sizes
      SELECT
        EXTRACT(month FROM pickup_datetime) month,
        COUNT(1) qty
      FROM
        `nyc-tlc.green.trips_2014`
      GROUP BY
        1)) )
SELECT
  -- cumulative sum = last row of former partition, add to new row count
  cumulative + ROW_NUMBER() OVER (PARTITION BY EXTRACT(month FROM pickup_datetime)) row,
  *
FROM
  `nyc-tlc.green.trips_2014`
-- import cumulative row counts
LEFT JOIN
  temp
ON
  (month= EXTRACT(month FROM pickup_datetime))

将其保存为新表后,您可以使用新行列进行查询而不会失去性能:

SELECT
  *
FROM
  `project.dataset.your_new_table`
WHERE
  row BETWEEN 10000001
  AND 10000100

相当麻烦,但诀窍。

答案 2 :(得分:0)

为什么不将结果表导出到GCS中?

如果您use wildcards,它会自动将表格拆分为文件,并且此导出只需要进行一次,而不是每次都查询并支付所有处理费用。

然后,您只需提供导出的文件,而不是提供对BQ API的调用结果。