如何提高表扫描的BigQuery性能?

时间:2016-07-07 18:03:18

标签: google-bigquery

我有一张包含大约8000万条金融交易记录的表格。我想找到每笔超过1亿美元的交易。此查询大约需要3秒钟,这对我的BI工具不起作用。

% time bq query --nouse_cache 'select * from kc_imports.all WHERE VALUE > 100000000'

时间结果是:

0.35s user 
0.10s system 
15% cpu 
2.899 total

有没有办法大幅度缩短完成查询的时间?如果是这样,有什么提示? Google Cloud是否提供某种类型的地图缩减工具?

我应该注意,后续查询可能有所不同,例如。我可能还想搜索低于500美元的所有交易。

3 个答案:

答案 0 :(得分:5)

让我们在公共桌面上运行一些查询,行数大于50亿。

SELECT *
FROM [fh-bigquery:wikipedia.pagecounts_201605] 
WHERE requests>1000

此查询耗时6.1s,运行超过357 GB。我们怎样才能让它更快?

SELECT COUNT(*) FROM (
  SELECT *
  FROM [fh-bigquery:wikipedia.pagecounts_201605] 
  WHERE requests>1000
)

5.8s,超过38.6 GB。它花了大约相同的时间,但是当只选择一列时,它询问了更少的数据(更便宜的查询)(BigQuery意识到获得此结果的唯一需要的列是requests)。

SELECT *
FROM [fh-bigquery:wikipedia.pagecounts_201605] 
WHERE requests>1000
LIMIT 500

1.7s,超过357 GB。与第一个查询几乎相同的查询,但是当我们添加LIMIT时速度更快。为什么?由于BigQuery在许多工作者之间划分任务,性能将受到最慢的性能的限制。如果我们将结果限制为500,则BigQuery不需要等待所有工作人员返回。

这里有一个有趣的结果:问题提到扫描8000万行花了6秒钟。在这个例子中,我在6秒内扫描了> 50亿行。这是关于BigQuery如何处理100倍数据的有趣可扩展性显示。

其他有趣的结果:

SELECT SUM(requests)
FROM [fh-bigquery:wikipedia.pagecounts_201105] 

1.6s,44亿行。

SELECT SUM(requests)
FROM [fh-bigquery:wikipedia.pagecounts_201306] 

1.8s,54亿行。

SELECT SUM(requests)
FROM [fh-bigquery:wikipedia.pagecounts_201605] 

5.3s,51亿行。

我们在这里见证了数据存储方面的一些偏差 - 这些表彼此非常相似,但201605的结果有所不同,它给我的结果比其他每个表都慢。通常我希望BigQuery能够不断优化数据的存储方式 - 自动而无需执行任何操作(https://cloud.google.com/blog/big-data/2016/04/inside-capacitor-bigquerys-next-generation-columnar-storage-format)。

答案 1 :(得分:2)

我可以提出一些建议,具体取决于您查询数据的方式:

  • 通过将查询限制为仅您真正需要的列来扫描较少的数据。

  • 最大限度地利用缓存(不要在您查询的表格中过于频繁地更改数据)

  • 作为数据加载过程的一部分,为超过100M的事务或您需要的任何其他值创建单独的表。当您查找这些交易的某些记录时,这将限制BQ需要扫描的记录数量。)

  • 避免使用非确定性查询,例如NOW()或TODAY(),因为它们不可缓存。

  • 考虑使用每日分区表[1],因为它也可以限制要扫描的数据量(如果您查找两个日期之间的交易)

  • 考虑使用表装饰器[2],特别是如果您只需查询最近的数据(即最后10分钟或最后一小时)

  • 如果您正在使用REGEXP_MATCH(),请考虑尽可能使用CONTAINS()..

  • 保持查询结果< 128MB,否则它也不会被缓存

最后,BigQuery的真正强大之处在于,当您的数据增长时,您的查询时间将会增加,但规模要小得多。但是,BigQuery确实对真正大的数据集很有吸引力,但它不是一个实时查询引擎 - 它的分析数据库。如果您需要1秒或亚秒响应,则需要在BigQuery之上添加额外的缓存层。

[1] https://cloud.google.com/bigquery/docs/creating-partitioned-tables

[2] https://cloud.google.com/bigquery/table-decorators

答案 2 :(得分:2)

SELECT * FROM KcTrade:kc_imports.all.VALUE WHERE VALUE > 100000000;

根据您的实际例子,很少有想法

  1. 使用SELECT *强制扫描桌子的所有列!你真的需要所有吗?仅指定所需的字段/列可以显着提高性能。
  2. 你需要所有行吗?使用LIMIT可以极大地提高性能!
  3. 终于来了!你在BI工具中实际做了什么? 最有可能是某种聚合/统计/等等。 为什么不在这里实现逻辑并输出结果。 重量级交易原始数据的输出本身就是耗时的 - 而低流量的聚合数据的输出很快
  4.   
        
    • 关于限制,我不能这样做,我需要所有的记录。
    •   
    • 因为该工具需要支持对整个数据集的任意探索
    •   

    您的特定用例的主要问题是,它不是BigQuery的用途!

      

    Google BigQuery是一项网络服务,可让您进行交互式分析   大量数据集 - 高达数十亿行。可扩展且易于使用,   BigQuery使开发人员和企业可以利用强大的数据   按需分析。

    BigQuery本身就是interactive analysis of massive datasets的工具! 因此,您的用例不是使用它的功能,而是仅使用BigQuery作为数据存储。您可以考虑使用其他数据库,例如索引等等。

    只想分享我的想法