Python 谷歌数据流:插入+;在流式管道中的BigQuery中更新
主要对象 一个python流式管道,在其中我从pub/sub读取输入 分析输入后,有两个选项可用:Python 谷歌数据流:插入+;在流式管道中的BigQuery中更新,python,google-bigquery,google-cloud-dataflow,apache-beam,Python,Google Bigquery,Google Cloud Dataflow,Apache Beam,主要对象 一个python流式管道,在其中我从pub/sub读取输入 分析输入后,有两个选项可用: 如果x=1->插入 如果x=2->更新 测试 这不能使用ApacheBeam函数来完成,因此您需要使用BigQuery的0.25API来开发它(目前这是Google Dataflow支持的版本) 问题 插入的记录仍在BigQuery缓冲区中,因此update语句失败: UPDATE or DELETE statement over table table would aff
- 如果x=1->插入
- 如果x=2->更新
测试
- 这不能使用ApacheBeam函数来完成,因此您需要使用BigQuery的0.25API来开发它(目前这是Google Dataflow支持的版本)
问题
- 插入的记录仍在BigQuery缓冲区中,因此update语句失败:
UPDATE or DELETE statement over table table would affect rows in the streaming buffer, which is not supported
代码 插入 更新
即使该行不在流式缓冲区中,在BigQuery中这仍然不是解决此问题的方法。BigQuery存储更适合批量突变,而不是通过
UPDATE
这样突变单个实体。您的模式与我期望从事务性而非分析性用例中得到的东西是一致的
为此,考虑一种基于追加的模式。每次处理实体消息时,通过流式插入将其写入BigQuery。然后,当需要时,您可以通过查询获得所有实体的最新版本
例如,让我们假设一个任意模式:idfield
是唯一的实体键/标识符,message\u time
表示消息发出的时间。您的实体可能有许多其他字段。要获取实体的最新版本,我们可以运行以下查询(并可能将其写入另一个表):
这种方法的另一个优点是,它还允许您在任意时间点执行分析。要在一小时前对实体的状态执行分析,只需添加WHERE子句:
WHERE message\u time,即使该行不在流式缓冲区中,这仍然不是BigQuery中解决此问题的方法。BigQuery存储更适合批量突变,而不是通过UPDATE
这样突变单个实体。您的模式与我期望从事务性而非分析性用例中得到的东西是一致的
为此,考虑一种基于追加的模式。每次处理实体消息时,通过流式插入将其写入BigQuery。然后,当需要时,您可以通过查询获得所有实体的最新版本
例如,让我们假设一个任意模式:idfield
是唯一的实体键/标识符,message\u time
表示消息发出的时间。您的实体可能有许多其他字段。要获取实体的最新版本,我们可以运行以下查询(并可能将其写入另一个表):
这种方法的另一个优点是,它还允许您在任意时间点执行分析。要在一小时前对实体的状态执行分析,只需添加WHERE子句:WHERE message\u time
def insertCanonicalBQ(input):
from google.cloud import bigquery
client = bigquery.Client(project='project')
dataset = client.dataset('dataset')
table = dataset.table('table' )
table.reload()
table.insert_data(
rows=[[values]])
def UpdateBQ(input):
from google.cloud import bigquery
import uuid
import time
client = bigquery.Client()
STD= "#standardSQL"
QUERY= STD + "\n" + """UPDATE table SET field1 = 'XXX' WHERE field2= 'YYY'"""
client.use_legacy_sql = False
query_job = client.run_async_query(query=QUERY, job_name='temp-query-job_{}'.format(uuid.uuid4())) # API request
query_job.begin()
while True:
query_job.reload() # Refreshes the state via a GET request.
if query_job.state == 'DONE':
if query_job.error_result:
raise RuntimeError(query_job.errors)
print "done"
return input
time.sleep(1)
#standardSQL
SELECT
idfield,
ARRAY_AGG(
t ORDER BY message_time DESC LIMIT 1
)[OFFSET(0)].* EXCEPT (idfield)
FROM `myproject.mydata.mytable` AS t
GROUP BY idfield