我正在运行以下功能来分析BigQuery查询:
# q = "SELECT * FROM bqtable LIMIT 1'''
def run_query(q):
t0 = time.time()
client = bigquery.Client()
t1 = time.time()
res = client.query(q)
t2 = time.time()
results = res.result()
t3 = time.time()
records = [_ for _ in results]
t4 = time.time()
print (records[0])
print ("Initialize BQClient: %.4f | ExecuteQuery: %.4f | FetchResults: %.4f | PrintRecords: %.4f | Total: %.4f | FromCache: %s" % (t1-t0, t2-t1, t3-t2, t4-t3, t4-t0, res.cache_hit))
然后,我得到如下信息:
初始化BQClient:0.0007 | ExecuteQuery:0.2854 | FetchResults:1.0659 |打印记录:0.0958 |总计:1.4478 | FromCache:正确
我正在GCP机器上运行此程序,它只能在美国(同一地区等)位置获取一个结果,因此(我希望?)网络传输应该可以忽略不计。是什么造成这里的所有开销?
我在GCP控制台上尝试了此操作,它说返回缓存命中所需的时间少于0.1s
,但实际上,这需要一秒钟多的时间。这是一个示例视频,用于说明:https://www.youtube.com/watch?v=dONZH1cCiJc。
第一个查询的通知,例如,它说它从缓存中以0.253s返回:
但是,如果您观看上述视频,则查询实际上是在7秒3帧时开始的-
它在8秒13帧时完成-
那是一秒钟多的时间-差不多一个半秒!该数字类似于我在python中从命令行执行查询时得到的数字。
那么,为什么然后它报告说实际上只花费了0.253s
来执行查询并返回一个结果,却花费了那五倍呢?
换句话说,查询时间似乎有第二次开销 REGARDLESS (在执行细节中根本没有指出)。有什么方法可以减少这个时间?
答案 0 :(得分:15)
用户界面报告的是查询执行时间,而不是总时间。
查询执行时间是BigQuery实际扫描数据和计算结果所花费的时间。如果它只是从缓存中读取数据,那么它将非常快,通常不到1秒,这反映了您所看到的时间。
但是,这不包括下载结果表并将其显示在UI中。您实际上是在Python脚本中进行了测量,该脚本显示了FetchResults
步骤耗时超过1秒钟,这与浏览器控制台中发生的情况相同。例如,包含数百万行的缓存查询结果将很快被执行,但完全下载可能需要30秒。
BigQuery是一个大型分析(OLAP)系统,设计用于吞吐量而不是延迟。它使用具有密集计划过程的分布式设计,并将所有结果写入临时表。这样一来,它可以在数秒内处理PB,但是要权衡的是,无论多么小,每个查询都将花费几秒钟来运行。
您可以查看official documentation以获得有关查询计划和性能的更多信息,但是在这种情况下,无法进一步减少延迟。目前,几秒钟是BigQuery的最佳情况。
如果您需要较短的响应时间来进行重复查询,则可以考虑将结果存储在自己的缓存层(例如Redis)中,或者使用BigQuery将数据聚合到更小的数据集中,然后将其存储在传统的关系数据库中(如Postgres或MySQL)。