BigQuery Storage API 无法读取由有序 (ORDER BY) 查询创建的临时表
Posted
技术标签:
【中文标题】BigQuery Storage API 无法读取由有序 (ORDER BY) 查询创建的临时表【英文标题】:BigQuery Storage API cannot read from a temporary table created by ordered (ORDER BY) queries 【发布时间】:2019-05-18 14:27:41 【问题描述】:Google 的 BigQuery Storage API 可以读取由仅涉及 SELECT、FROM 和 WHERE 的基本查询创建的临时表。
我看到的是,当您使用 ORDER BY 语句检索一组有序的行时,BigQuery 存储 API 无法读取创建的临时表。
看看下面的代码示例:
让我们来看看这个查询:
sql = """SELECT name FROM `bigquery-public-data.usa_names.usa_1910_current` LIMIT 1000"""
如果您使用此 BigQuery python API 代码运行它:
bq_client = bigquery.Client("myproject") ## << Change to your project
query_job = bq_client.query(
sql,
location='US')
project_id = query_job.destination.project
dataset_id = query_job.destination.dataset_id
table_id = query_job.destination.table_id
print("Destination table: " + project_id + "." + dataset_id + "." + table_id)
...然后你得到目标表。
从这里,您可以将此目标表传递给 BigQuery Storage API 以使用 RPC 获取结果:
client = bigquery_storage_v1beta1.BigQueryStorageClient()
table_ref = bigquery_storage_v1beta1.types.TableReference()
table_ref.project_id = project_id
table_ref.dataset_id = dataset_id
table_ref.table_id = table_id
read_options = bigquery_storage_v1beta1.types.TableReadOptions()
read_options.selected_fields.append("name")
parent = "projects/".format(project_id)
session = client.create_read_session(
table_ref, parent, table_modifiers=modifiers, read_options=read_options
) # API request.
reader = client.read_rows(
bigquery_storage_v1beta1.types.StreamPosition(stream=session.streams[0])
)
rows = reader.rows(session)
这很好用。
现在将sql= <yourquery>
中的查询更改为
sql = """SELECT name FROM `bigquery-public-data.usa_names.usa_1910_current` ORDER BY name ASC LIMIT 1000"""
您将从代码的 BigQuery Storage API 部分收到以下错误:
Table 'myproject:mydataset.temptable' has a storage format that is not supported.
这意味着查询中的 ORDER BY 语句增加了某种复杂性,使存储 API 无法读取临时表。
问题: 1)关于如何解决这个问题的任何想法,还是此时存储 API 的真正限制? 2) 如果 ORDER BY 产生问题,查询的全范围是多少 为存储 API 创建不可读的临时表?
【问题讨论】:
结果集的大小是多少? AFAIK,这与临时表的大小有关,而不是 ORDER BY。 BigQuery Storage API 可以从临时表中读取之前的阈值约为 100 MB。这可以通过在查询中显式设置目标表来解决。 如果您运行上面的代码示例,您会发现相同的结果:无论数据大小如何,通过将 ORDER BY 添加到查询中,您将无法再从临时表中读取。实际上,当您显式创建一个临时表作为目标时它可以工作,但不适用于隐式创建的表。 当我运行代码示例时(将修饰符设置为 None,因为这没有定义),我首先得到错误400 there was an error creating the session: the table has a storage format that is not supported
,没有设置 ORDER BY,然后使用 ORDER BY 设置我得到 400 The following selected fields do not exist in the table schema: name
。
【参考方案1】:
我们可以使用 bigquery_storage.BigQueryReadClient 从由 order by、join 等查询创建的临时表中读取数据。下面是工作代码。 我已经使用 join 创建了临时表。
from google.cloud.bigquery_storage import BigQueryReadClient
from google.cloud.bigquery_storage import types, ReadRowsResponse
bqclient = bigquery.Client(credentials=credentials, project=your_project_id,)
client = bigquery_storage.BigQueryReadClient(credentials=credentials)
try:
import fastavro
except ImportError:
fastavro = None
sql = """SELECT s.id, s.name, d.dept FROM sbx-test.EMP.emp01 s join sbx-test.EMP.dept d
on s.id = d.id"""
query_job = bqclient.query(sql)
project_id = query_job.destination.project
dataset_id = query_job.destination.dataset_id
table_id = query_job.destination.table_id
table = "projects//datasets//tables/".format(
project_id, dataset_id, table_id
)
requested_session = types.ReadSession()
requested_session.table = table
requested_session.data_format = types.DataFormat.AVRO
requested_session.read_options.selected_fields = ["name", "dept"]
parent = "projects/".format(project_id)
session = client.create_read_session(
parent=parent,
read_session=requested_session,
max_stream_count=1,
)
reader = client.read_rows(session.streams[0].name)
rows = reader.rows(session)
names = set()
depts = set()
for row in rows:
names.add(row["name"])
depts.add(row["dept"])
print("Got unique employees and departments ".format(names, depts))
【讨论】:
以上是关于BigQuery Storage API 无法读取由有序 (ORDER BY) 查询创建的临时表的主要内容,如果未能解决你的问题,请参考以下文章
Google Spark-BigQuery-Connector如何利用BigQuery Storage API?
通过 Spark 使用 BigQuery Storage API:请求多个分区但仅获得 1 个
Bigquery API:如何为 load_table_from_storage 调用提供架构
bigquery storage API:是不是可以将 AVRO 文件直接流式传输/保存到 Google Cloud Storage?
如何使用 API 存储在 Google Cloud Storage 中的架构文件在 BigQuery 加载作业上设置架构?