【问题标题】:BigQuery - Query time becomes extremely longBigQuery - 查询时间变得非常长
【发布时间】:2016-01-15 02:06:49
【问题描述】:

最近我的所有查询都花费了很长时间,但基本上都没有消耗任何数据。

例如,对于一个非常简单的查询

Start Time: Jan 14, 2016, 12:35:13 PM
End Time: Jan 14, 2016, 12:35:15 PM
Bytes Processed: 0 B
Bytes Billed: 0 B
Billing Tier: 1
Destination Table: ****************.******************
Write Preference: Append to table
Allow Large Results: true
Flatten Results: true

这是我从 BQ 控制台得到的信息,告诉我这个查询不消耗任何数据(确实如此),只需要两秒钟。

但是当我在控制台中通过单击查询历史记录中的Run Query 再次运行此查询时,实际上需要 27 秒。之后,控制台中的Query History 再次显示此查询需要 2 秒。

基本上这个数据集中的所有查询都有这个问题。

我在这个数据集中有超过 40000 个表。

所以我的猜测是,在 BQ 实际运行查询之前,它首先找到要使用的表。然后它开始执行查询,这里是查询历史中的start time

如果是这样,我应该如何解决它,为什么需要这么长时间?

这是我提到的查询(做了一些更改):

select "some_id", '2015-12-01', if (count(user_id) == 0, NULL, sum(users_in_today_again) / count(user_id)) as retention
from
(
select
  users_in_last_day.user_id as user_id,
  if(users_in_today.user_id is null, 0, 1) as users_in_today_again
FROM
(
select user_id
from
  table_date_range(ds.sessions_some_id_, date_add(timestamp('2015-12-01'), -1, "DAY"), date_add(timestamp('2015-12-01'), -1, "DAY"))
group by user_id
) as users_in_last_day
left join
(
select user_id
from table_date_range(ds.sessions_some_id_, timestamp('2015-12-01'), timestamp('2015-12-01'))
group by user_id
) as users_in_today
on users_in_last_day.user_id = users_in_today.user_id
)

提前致谢!

【问题讨论】:

  • 哎呀!这是一个非常讨厌的查询。如果您正在做如此复杂的事情,我强烈建议您以编程方式发出查询,并且基本上执行一系列查询,您可以在其中获取一个查询的输出以以编程方式生成下一个查询。在这里的问题中,我认为您提到“count(user_id)”可能会导致整个表在每条记录上被迭代以计算用户数。尝试先单独发出计数查询,然后在后续过程中引用它的值。
  • (Cloud Dataflow 可能是此处使用 BigQuery 的另一种选择)。
  • @MichaelAaronSafyan 感谢您的回复。我不认为处理的行数是这个问题的原因。正如我所提到的,这个查询没有处理任何数据。表 session_some_id_20151201 为空。而且我尝试按照您的建议从顶部删除count(user_id),时间没有改变。

标签: google-bigquery


【解决方案1】:
PART 1

您可以使用Jobs:Get API 和从 BQ 控制台中的查询历史记录中获取的 jobid 来检查您关于延迟的理论。
正如您在Job Resources - statistics 参数中看到的那样,除了startTimeendTime 还有creationTime

PART 2

这里是在黑暗中拍摄,但在下面试试

SELECT "some_id", '2015-12-01', IF (COUNT(user_id) == 0, NULL, SUM(users_in_today_again) / COUNT(user_id)) AS retention
FROM
(
  SELECT
    users_in_last_day.user_id AS user_id,
    IF(users_in_today.user_id IS NULL, 0, 1) AS users_in_today_again
  FROM
  (
    SELECT user_id FROM (
      SELECT user_id, ROW_NUMBER() OVER(PARTITION BY user_id) AS pos
      FROM TABLE_DATE_RANGE(ds.sessions_some_id_, DATE_ADD(TIMESTAMP('2015-12-01'), -1, "DAY"), DATE_ADD(TIMESTAMP('2015-12-01'), -1, "DAY"))
    ) WHERE pos = 1
  ) AS users_in_last_day
  LEFT JOIN
  (
    SELECT user_id FROM (
      SELECT user_id, ROW_NUMBER() OVER(PARTITION BY user_id) AS pos
      FROM TABLE_DATE_RANGE(ds.sessions_some_id_, TIMESTAMP('2015-12-01'), TIMESTAMP('2015-12-01'))
    ) WHERE pos = 1
  ) AS users_in_today
  ON users_in_last_day.user_id = users_in_today.user_id 
)

我知道,它可能看起来很傻,但是这个版本的解释统计(基于一些虚拟数据) 与有问题的版本完全不同

我的猜测是原始版本中的重读/计算 Stage1/2 可能导致问题延迟

猜猜

【讨论】:

  • 非常感谢!你说的对。我尝试运行查询并检查了creationTimestartTimeendTime。 creationTime 和startTime 之间的延迟为25 秒,而startTimeendTime 之间的延迟接近0 秒。知道为什么第一次延迟这么大吗?
  • 所以,你的问题的第一部分相对容易。对于第二部分,想想你还能提供什么来帮助回答它
  • 在我的回答中添加了第 2 部分
  • 感谢您的更新!那很棒!最好将group 更改为partitionwhere 的组合。但问题是我的ds.sessions_some_id_20151201 是空的。这就是我认为延迟是由表定位引起的原因。我刚刚通过将ds.sessions_some_id_20151201ds.sessions_some_id_20151130(两个空表)复制到另一个空数据集来运行另一个实验,当我在那里运行这个查询时,只用了不到一秒钟。
【解决方案2】:

正如 Mikhail 问题的评论线程中所暗示的,大部分时间可能都花在了评估查询中的 TABLE_DATE_RANGE 函数上。该时间目前在查询统计中占creationTimestartTime 之间。

一般来说,使用TABLE_DATE_RANGETABLE_QUERY<dataset>.__TABLES__ 元表时,数据集中的数万或数十万个表会导致性能下降。我们正在努力更新我们的公共文档以提及这一点。

我的建议是,如果您想在数据集上使用表通配符,请确保其中没有太多表。如果该解决方案对您来说不可行,请告诉我们 BigQuery 是否可以在我们的issue tracker 上支持让您的用例更轻松的功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 2020-11-21
    • 2020-09-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    相关资源
    最近更新 更多