在摄取时进行分区时,Bigquery中的数据查询延迟的原因是什么



我使用bigquerypython应用程序批处理insert数据。表为摄入时的partitioned。我看到的不同之处在于,我插入的数据在摄入后1.5小时后会出现query

后来我把schema改成了timestamp

这一次,我可以在摄入后立即获得query数据。

为什么表schema中的_PARTITIONTIME伪列与timestamp列之间的行为存在差异?

蟒蛇吞食代码:

这是代码的简化版本:

bigquery_client = bigquery.Client()
TABLE_REF = bigquery_client.dataset('DATASET_ID').table('TABLE_ID')
TABLE = bigquery_client.get_table(TABLE_REF)
def ingest_to_bq(data: LIST[LIST]):
bigquery_client.insert_rows(TABLE, data)

表架构:

[
{
"name": "epoch_ms",
"type": "INTEGER",
"mode": "REQUIRED"
},
{
"name": "application_id",
"type": "STRING",
"mode": "REQUIRED"
},
{
"name": "ack_id",
"type": "STRING",
"mode": "REQUIRED"
},
{
"name": "data",
"type": "STRING",
"mode": "REQUIRED"
}
]

从BIGQUERY接口创建表,并在摄取时进行分区。

查询:

我使用BIGQUERY接口再次查询。

SELECT data from <DATASET_ID>.<TABLE_ID> WHERE _PARTITIONTIME="2020-03-30"

上面的查询不会显示半小时前摄入的结果。摄入后大约需要1.5小时才能得到结果。

新方案:

[
{
"name": "send_timestamp",
"type": "TIMESTAMP",
"mode": "REQUIRED"
},
{
"name": "application_id",
"type": "STRING",
"mode": "REQUIRED"
},
{
"name": "ack_id",
"type": "STRING",
"mode": "REQUIRED"
},
{
"name": "data",
"type": "STRING",
"mode": "REQUIRED"
}
]

查询新方案:

SELECT data from <DATASET_ID>.<TABLE_ID> WHERE send_timestamp>="2020-03-30 00:00:00" and send_timestamp<="2020-03-30 23:59:59"

此查询会在摄入后立即返回结果。我不必等待。

延迟的原因是BigQuery流缓冲区。流缓冲区是一种保留最近插入的行并针对写入吞吐量进行优化的缓冲区。换言之,当您将流式数据插入BigQuery时,您的数据首先会插入流式缓冲区,在该缓冲区中最多停留90分钟。在这一点上,数据被认为是持久的,你可以查询它,但你不允许对它进行一些特定的操作

正如您在文档中看到的,当数据位于流缓冲区中时,_PARTITIONTIME伪列将为NULL。鉴于此,您的查询无法找到新插入的行,因为您的_PARTITIONTIMENULL。为了确保最近插入的数据的伪列中的值是NULL,可以运行下面的查询。

  1. 如果要查看所有行的伪列,请运行SELECT *, _PARTITIONTIME p from <DATASET_ID>.<TABLE_ID>

  2. 如果要获取伪列为null的所有行,请运行SELECT * from <DATASET_ID>.<TABLE_ID> WHERE _PARTITIONTIME is null

最后,我想为这个主题添加一些有用的参考资料。

  1. BigQuery分区表的引用
  2. BigQuery流引用
  3. 一篇关于流到BigQuery的官方文章,讨论了流缓冲区以及如何处理它

我希望它能帮助

最新更新