BigQuery - 集群表不使用多个键减少查询大小

Posted

技术标签:

【中文标题】BigQuery - 集群表不使用多个键减少查询大小【英文标题】:BigQuery - Clustered tables not reducing query size with multiple keys 【发布时间】:2018-08-07 05:10:33 【问题描述】:

我正在尝试优化我在 BigQuery 中的查询成本,并且我一直在尝试聚集表。 供参考:BigQuery - querying only a subset of keys in a table with key value schema

按单列对表进行聚类成功地减少了我的查询大小。但是,使用多列(示例显示在:https://cloud.google.com/bigquery/docs/querying-clustered-tables#sample_table_used_in_the_examples)不会导致查询大小的任何减少。

要使用文档中给出的示例,

SELECT
  SUM(totalSale)
FROM
  mydataset.ClusteredSalesData
WHERE
  customer_id = 10000
  AND product_id LIKE 'gcp_analytics%'

如果表上没有集群,这会查询整个数据集(比如 100GB),当仅由 customer_id 集群时减少到大约 10GB(在实际运行后看到,而不是在验证器上),但根本没有变化当同时被 customer_id 和 product_id 聚类时(即使在实际运行查询之后)。

我已尝试更改聚类的顺序、WHERE 子句的顺序等。似乎没有任何改变。

这是预期的行为吗? BigQuery 上的错误?还是我做错了什么?

更新: 感谢@Pentium10 指点我:https://medium.com/@hoffa/bigquery-optimized-cluster-your-tables-65e2f684594b

要使用博文中的示例,在以下两个查询中,

第一季度:

SELECT wiki, SUM(views) views
FROM fh-bigquery.wikipedia_v3.pageviews_2017
WHERE DATE(datehour) BETWEEN '2017-06-01' AND '2017-06-30'
AND wiki = 'en'
--AND title = 'Barcelona'
GROUP BY wiki ORDER BY wiki

第二季度:

SELECT wiki, SUM(views) views
FROM fh-bigquery.wikipedia_v3.pageviews_2017
WHERE DATE(datehour) BETWEEN '2017-06-01' AND '2017-06-30'
AND wiki = 'en'
AND title = 'Barcelona'
GROUP BY wiki ORDER BY wiki

我原以为第二季度会更便宜,因为集群是按 (wiki, title) 进行的,但情况似乎并非如此。

【问题讨论】:

所有 BigQuery 表中的数据都存储在块中。对于集群表,数据是集群的,因此一个块可能只包含单个集群的数据。扫描聚簇表时,仅对匹配的簇/块收费。如果按 customer_id 过滤已经减少到块的 1/10,则按 product_id 过滤可能不会导致更少的块。例如,如果 customer_id = 10000 已经减少到 1 个块,按 product_id 过滤不会进一步降低成本。 有道理,这就是我理解单列聚类的方式。但是,当表使用多列聚集在一起时,这是如何工作的呢?在我看来,它必须结合指定的主要和次要列的值对其进行分块,因此添加辅助 product_id 过滤器必须只过滤块的子集。 @error_magnet 阅读:medium.com/@hoffa/… @Pentium10 谢谢,没见过这个。将使用此更新我的问题。 这取决于数据的大小。 BigQuery 会尝试保持最佳的块大小。如果 customer_id 10000 的数据小于最佳块大小,则所有数据将驻留在一个块中,按 product_id 过滤将无济于事;如果数据足够大以至于它驻留在两个块中,则按 product_id 过滤可以进一步将成本从 2 降低到 1。块 1:customer_id 10000,product_id "aaa" 到 "ppp"。块 2:customer_id 10000,product_id "qqq" 到 "zzz"。 【参考方案1】:

在您的查询 1 (Q1) 中 - 处理 86.1 GB 的估计成本为 0.43 美元 - 实际计费字节数 - 18.4 GB

对于第二季度 - 处理 180 GB 的估计成本为 0.90 美元 - 实际计费字节数 - 10.3 GB

对我来说听起来更便宜 :o)

但实际上,save 不仅仅是down to 10.3 GB from 18.4 GB——它实际上是down to 10.3 GB from 38.6 GB。这是因为在第一季度根本没有涉及title 列,而在第二季度却是! 因此,要将苹果与苹果进行比较 - 您可以添加 title,如下所示 - 您将看到估计成本为 180 GB - 而实际字节数计费 - 38.6 GB

第三季度:

SELECT wiki, title, SUM(views) views
FROM `fh-bigquery.wikipedia_v3.pageviews_2017`
WHERE DATE(datehour) BETWEEN '2017-06-01' AND '2017-06-30'
AND wiki = 'en'
-- AND title = 'Barcelona'
GROUP BY wiki, title   

注意/提醒:当您查询聚簇表时 - 估计仅基于分区显示(截至目前 - 我的理解是稍后这将被修复/改进)

【讨论】:

【参考方案2】:

我测试了基于this post 的下一个查询,由Pentium10 建议:

SELECT wiki, SUM(views) views 
FROM `fh-bigquery.wikipedia_v3.pageviews_2017` 
WHERE DATE(datehour) BETWEEN '2017-06-01' AND '2017-06-30' 
AND wiki = 'en' 
AND title = 'Barcelona' 
GROUP BY wiki ORDER BY wiki 

已处理 180.19GB(根据validator)。运行查询时处理了 10.3GB。

SELECT wiki, SUM(views) views 
FROM `fh-bigquery.wikipedia_v3.pageviews_2017` 
WHERE DATE(datehour) BETWEEN '2017-06-01' AND '2017-06-30' 
AND wiki = 'en' 
--AND title = 'Barcelona' 
GROUP BY wiki ORDER BY wiki 

已处理 86.1GB(根据validator)。 运行查询时处理了 18.4GB。

SELECT wiki, SUM(views) views 
FROM `fh-bigquery.wikipedia_v3.pageviews_2017` 
WHERE DATE(datehour) BETWEEN '2017-06-01' AND '2017-06-30' 
-- AND wiki = 'en' 
AND title = 'Barcelona' 
GROUP BY wiki ORDER BY wiki 

已处理 180.19GB(根据validator)。 运行查询时处理了 113.85GB。

一切看起来都是连贯的,因为正如 Hoffa 先生所说,集群表的“顺序很重要”(“wiki”比“title”节省更多)。

验证器仍然无法正常工作是真的,但clustered tables 是still on beta,所以我们可以期待未来的改进。

【讨论】:

聚集表的一个问题是,在运行查询之前无法提供准确的成本估算。我们使用运行时可用的信息来降低成本并提高性能。对于聚簇表,我们将尝试使此成本估算更严格,但在许多情况下,该估算只会是一个上限。

以上是关于BigQuery - 集群表不使用多个键减少查询大小的主要内容,如果未能解决你的问题,请参考以下文章

Bigquery 集群不会降低查询成本

BigQuery 通配符表 - 有啥限制?

bigrquery:使用 geoJSON 文件创建 BigQuery 表不起作用

使用 bigquery 对数据存储键进行连接

如何下载在 BigQuery 中进行的所有查询?

Google Cloud Dataproc 删除 BigQuery 表不起作用