我有一个行为奇怪的查询,因为在某些情况下需要 120 秒,另外需要 250 秒。我必须最小化执行时间,但找不到指南来帮助我改进查询的运行时。
包含信息的表具有以下特征:
- 所有字段都是重复的
- 它有8亿条记录
- 进程 14.2 GB
查询是这样的:
SELECT
todayInfo.client AS Client,
todayInfo.todayInfo AS Today,
todayInfo.dayAgoInfo AS DayAgo,
todayInfo.threeDaysAgo AS ThreeDaysAgo,
todayInfo.weekAgo AS weekAgo,
FROM (
SELECT
client,
SUM(IF( bp_Time BETWEEN TIMESTAMP('2016/01/01')
AND TIMESTAMP('2016/01/31'),1,0)) AS todayInfo,
SUM(IF( bp_Time BETWEEN DATE_ADD(TIMESTAMP('2016/01/01'), - 1,"DAY")
AND DATE_ADD(TIMESTAMP('2016/01/31'), - 1,"DAY"),1,0)) AS dayAgoInfo,
SUM(IF( bp_Time BETWEEN DATE_ADD(TIMESTAMP('2016/01/01'), - 3,"DAY")
AND DATE_ADD(TIMESTAMP('2016/01/31'), - 3,"DAY"),1,0)) AS threeDaysAgo,
SUM(IF( bp_Time BETWEEN DATE_ADD(TIMESTAMP('2016/01/01'), - 8,"DAY")
AND DATE_ADD(TIMESTAMP('2016/01/31'), - 8,"DAY"),1,0)) AS weekAgo
FROM
[dataset.table]
GROUP BY
client
) AS todayInfo
ORDER BY
Today DESC
LIMIT 10
是否有指南或提示可以帮助我优化运行时,不仅此查询,而且将来的查询?
由于 BigQuery 的工作方式,它不像关系数据库那样可调。它不使用索引,每个查询都是完全扫描。
话虽如此,您需要详细了解查询速度缓慢的原因。这在很大程度上取决于数据的具体情况。您可以使用查询计划说明来很好地了解 BigQuery 将时间花在哪里。
但是,正如@Pentium10评论中提到的,您可能必须按天对数据进行分区以减少扫描大小。在这个答案中对此进行了更详细的解释。
在此链接中,您可以找到有关 BigQuery 如何在幕后工作的更多信息。了解槽位是优化查询的关键。插槽是计算能力的单位,数据根据连接、排序依据、分组依据、函数、子查询等在它们之间随机排列。
在您的情况下,当您在查询中计算"SUM"、"IF"、"BETWEEN"时,您需要更多计算。一些在您的情况下有用的函数是"DATE_SUB"和 countif()。
SELECT countif((DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))=end_date) as AS dayAgoInfo from [dataset.table];