首页 > 解决方案 > 超过 bigquery insertAll 方法的速率限制

问题描述

我将烧瓶端点部署到 Google AppEngine。它接收有效负载,对其进行解析,然后将数据发送到两个不同的 bigquery 表。

我的设置:我正在使用python 3.7flaskgoogle AppEnginegoogle.cloud.bigquery Client()类。

简而言之,这就是发生的事情:

- endpoint is called
- endpoint gets payload and parses it
- sends data (1 row) to first bigquery table using client.insert_rows_json(table, [data])
- sends data (1 row) to second bigquery table using client.insert_rows(table, [data])

错误:

阅读我的服务的 appengine 日志,我发现了这个错误:

https://cloud.google.com/bigquery/docs/reference/rest/v2/tabledata/insertAll
Traceback (most recent call last): File "/env/lib/python3.7/site-packages/google/api_core/retry.py", line 184, in retry_target return target() File "/env/lib/python3.7/site-packages/google/cloud/_http.py", line 423, in api_request raise exceptions.from_http_response(response) google.api_core.exceptions.Forbidden: 403 GET https://bigquery.googleapis.com/bigquery/v2/projects/PROJECT_NAME/datasets/DATASET_NAME/tables/TABLE_NAME: Exceeded rate limits: too many api requests per user per method for this user_method. For more information, see https://cloud.google.com/bigquery/troubleshooting-errors

我的假设是对 BQ API 的两次调用超过了用户方法限制,这是否合理?由于两个 Client() 方法都使用相同的 API 方法 insertAll,即 a streaming method,我怀疑这是配额问题。

我发现的另一个问题是,第一次调用填充的表比第二次调用填充的表少了约 2% 的条目(这是我注意到错误的表)。可能是什么原因?

我已经检查了第一个表中不存在的一些有效负载,它们是合法的,所以我认为它们的格式与表模式不匹配不是问题。

编辑:解决了

我最终按照 shollyman 的建议删除了 get_table,而是将使用 TableReference 初始化的 Table 对象和作为 SchemaField 实例列表的模式传递给 insert_rows( )insert_rows_json ( )

代码:

from google.cloud import bigquery
client = bigquery.Client()

老的

# get table info -- API call
table_id = '{}.{}.{}'.format(PROJECT_ID, DATASET_ID, TABLE_ID)
table = client.get_table(table_id)
# insert row -- API call
client.insert_rows(table, [data])

新的

# create table ref
dataset_ref = bigquery.dataset.DatasetReference(project=PROJECT_ID, dataset_id=DATASET_ID)
table_ref = bigquery.table.TableReference(dataset_ref=dataset_ref, table_id=TABLE_ID)
# specify table schema
schema = [
        bigquery.schema.SchemaField(name='field1', field_type='TIMESTAMP', mode='NULLABLE'),
        bigquery.schema.SchemaField(name='field2', field_type='STRING', mode='NULLABLE')
              ]
# create table instance 
table = bigquery.table.Table(table_ref=table_ref, schema=schema)
# insert row -- API call
client.insert_rows(table, [data])

标签: python-3.xgoogle-bigquery

解决方案


这表明您的代码通过tables.get API过于激进地获取表元数据。您是否会在每次插入时重新加载表统计信息或获取模式等?与检索表元数据相比,流式插入允许更多数量级的 QPS。


推荐阅读