【问题标题】:Working with large offsets in BigQuery在 BigQuery 中使用大偏移量
【发布时间】:2018-08-11 04:21:40
【问题描述】:

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

是否有更好的方法可以在 BigQuery 中使用相当于“偏移量”而不出现性能下降的情况?我知道这可能需要一个不存在的灵丹妙药,但想知道是否有解决方法来实现上述目标。如果没有,如果有人可以提出一种替代方法来获得上述内容(例如 kinetica 或 cassandra 或任何其他方法),那将不胜感激。

【问题讨论】:

  • 你能从实际的角度阐明这样做的原因吗?
  • @MikhailBerlyant 一个示例是产品目录(约 10M 条目),用户希望向下滚动到以字母“M”开头的项目。这是我发现自己每天在 Excel 中执行的一项任务(在大约 500k-1M 行的电子表格上)。
  • 为什么不使用WHERE LOWER(product_name) > 'm'之类的东西?
  • @MikhailBerlyant 是的,这会起作用,但我更多的是描述前端用户的随机搜索行为模式,例如,如果他们去 m,然后是 z,然后是 c ,然后是 a 等等。或者,如果该字段是日期时间字段,他们是否每次都必须输入完整的日期时间?
  • 我想说 - 由应用程序的 UI 来使用户与您的应用程序的交互尽可能友好和舒适。所以最有可能 - 是的 - 用户需要以某种方式输入他们想要开始的内容 - 这可以是简单的条目或某种日历控件 - 抱歉,如果我在这里走错方向

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


【解决方案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

相当麻烦,但可以解决问题。

【讨论】:

  • 非常有趣和有创意的解决方案。虽然我尝试了超过 100 秒才能运行,但它确实有效。
  • 您的意思是创建表?我猜可以通过更多分区使其更快。这应该是可扩展的,直到您达到最大插槽数。
  • 调查@David542 问题和他的cmets 提出问题并且很难看到这个答案实际上是如何回答所有这些问题的。我可能需要休息一下然后回到这里:o)无论如何 - 干得好 - 恭喜获得丰厚的赏金:o)
  • 这是我和 Dan 的共同努力:虽然他解释了为什么没有好的方法来解决这个问题,因为它超出了 bq 的目的 - 我提供了在如果表已经存在。由于该方法可扩展且有效,我不明白为什么它不是一个可行的答案?!
  • @MartinWeitzmann - 没关系。只要 OP 认为它回答了他的问题 - 它就是!我只是印象深刻(基于他的声明 - but I'm more describing a random seek pattern of behavior for the user on the front-end, for example what if they go to m, then z, then c, then a, etc. Or, if the field is a date-time field ...),OP 想要更通用和动态的东西(与预生成相比),这显然是无法实现的。无论如何 - 干得好 :o)
【解决方案2】:

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

如果你use wildcards,它会自动将表拆分为文件,并且这个导出只需要完成一次,而不是每次查询并支付所有处理费用。

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

【讨论】:

  • 如果行数超过 16,000 行,BigQuery 将无法导出。
【解决方案3】:

在 BigQuery 等系统中,偏移量通过读取并丢弃所有结果直到偏移量起作用。

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

例如,假设您想按费率代码、上车和下车时间查看出租车行程:

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

如果你是通过 OFFSET 100000 做的,需要 4s,第一行是:

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

如果我使用了那些日期和速率值而不是偏移量,则查询只需要 2.9 秒:

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 中)查找最接近的日期/分钟,然后将该用户查询转换为上述更高效的版本。

【讨论】:

  • 你能举个例子吗?假设有两个字段,id(自动递增)和bool(真/假)。如果用户想要按 bool desc、id asc 排序并获得 150M-151M 的条目,他们会怎么做? ...这可能是一个微不足道的例子,但是假设有一个复杂的排序添加了多个列,如何以广义的方式使用一个列作为下限?
  • 抱歉,在一场足球比赛之前,我在手机上这样做了。没有真正有效的方法来获取准确的行号,除非您已经将其作为显式列,否则您必须将其传递给您要查询的列,例如 x 之后的自动 ID
  • 未来是否有计划允许在 BQ 中任意偏移而不会出现 resourceExceeded 错误?
  • 我是第一个请求此功能的人,还是其他人也要求类似的功能?
猜你喜欢
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多