确定何时在BigQuery中对表进行分区的最佳平衡是什么?

Fel*_*ffa 6 database-cluster database-partitioning google-bigquery

我们正在使用公共数据集对BigQuery进行基准测试。我们使用了同一张表并按天对其进行了分区,但是尚不清楚我们会获得很多好处。有什么好的平衡点?

SELECT  sum(score) 
FROM `fh-bigquery.stackoverflow_archive.201906_posts_questions` 
WHERE creation_date > "2019-01-01" 
Run Code Online (Sandbox Code Playgroud)

耗时1秒,处理270.7MB。

相同,但具有分区:

SELECT  sum(score) 
FROM `temp.questions_partitioned` 
WHERE creation_date > "2019-01-01"
Run Code Online (Sandbox Code Playgroud)

耗时2秒,处理14.3 MB。

因此,我们发现在处理的MB中有好处,但查询速度较慢。

决定何时进行分区的好策略是什么?

(从我今天收到的电子邮件中)

Fel*_*ffa 8

对表进行分区时,您需要考虑每个分区有足够的数据。将每个分区都视为一个不同的文件-打开365个文件可能比拥有一个大文件要慢。

在这种情况下,用于基准测试的表具有2019年1.6 GB的数据(直到本月的6月)。每天每个分区有1.6GB / 180 = 9 MB的数据。

对于如此低的数据量-将其安排在每日分区中不会带来太多好处。考虑改为按年份对数据进行分区。请参阅以下问题以了解如何:

另一种选择是根本不对表进行分区,而是使用聚类按日期对数据进行排序。然后BigQuery可以选择每个块的理想大小。

如果要运行自己的基准,请执行以下操作:

CREATE TABLE `temp.questions_partitioned`
PARTITION BY DATE(creation_date)
AS
SELECT *
FROM `fh-bigquery.stackoverflow_archive.201906_posts_questions` 
Run Code Online (Sandbox Code Playgroud)

VS没有分区,只是按日期聚类:

CREATE TABLE `temp.questions_clustered`
PARTITION BY fake_date
CLUSTER BY creation_date
AS

SELECT *, DATE('2000-01-01') fake_date  
FROM `fh-bigquery.stackoverflow_archive.201906_posts_questions` 
Run Code Online (Sandbox Code Playgroud)

然后,我对集群表的查询将是:

SELECT sum(score) 
FROM `temp.questions_clustered`
WHERE creation_date > "2019-01-01" 
Run Code Online (Sandbox Code Playgroud)

花费了0.5秒,处理了17 MB。

比较:

  • 原始表格:1秒,270.7MB
  • 分区:2秒,14.3 MB
  • 群集:0.5秒,17 MB

我们有赢家!群集将每日数据(对于该表来说不算多)将其组织成比按日严格划分数据更有效的块。

查看这些表上每个查询的执行细节也很有趣:

消耗的插槽时间

  • 原始表:10.683秒
  • 分区:7.308秒
  • 聚类:0.718秒

如您所见,对原始表的查询使用了大量的插槽(并行性)以在1秒内获得结果。在这种情况下,有50名工人用多年的数据处理了整个表,读取了1770万行。在分区表上的查询必须使用很多插槽-但这是因为每个插槽都分配了较小的每日分区,该读取使用了超过0.9M行的153个并行工作器。相反,集群查询能够使用很少的插槽。数据井井有条,可以由57个并行工作人员读取,读取112万行。

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

也可以看看: