【问题标题】:BigQuery - Check if table already existsBigQuery - 检查表是否已存在
【发布时间】:2015-04-28 03:50:28
【问题描述】:

我在 BigQuery 中有一个数据集。该数据集包含多个表。

我正在使用 BigQuery API 以编程方式执行以下步骤:

  1. 查询数据集中的表 - 由于我的响应太大,我启用 allowLargeResults 参数并将我的响应转移到目标表。

  2. 然后我将数据从目标表导出到 GCS 存储桶。

要求:

  • 假设我的流程在第 2 步失败,我想重新运行此步骤。

  • 但在我重新运行之前,我想检查/验证名为“xyz”的特定目标表是否已存在于数据集中。

  • 如果存在,我想重新运行第 2 步。

  • 如果不存在,我想做foo。

我该怎么做?

提前致谢。

【问题讨论】:

  • 你有没有研究过写作倾向?你实际上可以做一些叫做“write_if_empty”的事情,如果表上有任何数据,它就会阻塞。或“Write_truncate”,它将用您当前的数据替换现有数据。
  • 我确实调查过了。我想在导出到 GCS 之前检查表是否存在。而不是在写入目标表之前。 write disposition 参数仅在您想要将数据加载到表中、查询表和复制现有表时可用。但不是在提取到 GCS 时。这是我的理解。我可能错了。有什么想法吗?
  • 不不,你完全正确。你的问题似乎很广泛,所以我不能 100% 确定你想在哪里发现问题。好吧,我的意思是....您使用的是什么语言? :P 我们需要对这个问题有所了解才能对其进行调查。 BigQuery API 肯定有一种方法可以查看表是否存在......
  • 您是否正在寻找一种 API 方式来执行此操作(例如,请参阅cloud.google.com/bigquery/docs/reference/v2/tables/get 上的 tables.get)?或者使用 bq 客户端进行测试的方法(bq show dataset.table)?

标签: google-api export google-bigquery google-cloud-storage


【解决方案1】:

Alex F 的解决方案适用于 v0.27,但不适用于更高版本。为了migrate to v0.28+,以下解决方案将起作用。

from google.cloud import bigquery

project_nm = 'gc_project_nm'
dataset_nm = 'ds_nm'
table_nm = 'tbl_nm'

client = bigquery.Client(project_nm)
dataset = client.dataset(dataset_nm)
table_ref = dataset.table(table_nm)

def if_tbl_exists(client, table_ref):
    from google.cloud.exceptions import NotFound
    try:
        client.get_table(table_ref)
        return True
    except NotFound:
        return False

if_tbl_exists(client, table_ref)

【讨论】:

    【解决方案2】:

    这是一个 python sn-p,它会判断一个表是否存在(在过程中删除它——小心!):

    def doesTableExist(project_id, dataset_id, table_id):
      bq.tables().delete(
          projectId=project_id, 
          datasetId=dataset_id,
          tableId=table_id).execute()
      return False
    

    或者,如果您不想在此过程中删除表,您可以尝试:

    def doesTableExist(project_id, dataset_id, table_id):
      try:
        bq.tables().get(
            projectId=project_id, 
            datasetId=dataset_id,
            tableId=table_id).execute()
        return True
      except HttpError, err
        if err.resp.status <> 404:
           raise
        return False
    

    如果你想知道bq来自哪里,你可以从这里拨打build_bq_clienthttp://code.google.com/p/bigquery-e2e/source/browse/samples/ch12/auth.py

    一般来说,如果您使用它来测试是否应该运行会修改表的作业,那么最好还是直接执行该作业,并使用WRITE_TRUNCATE 作为写入处置。

    另一种方法是创建可预测的作业 ID,然后使用该 ID 重试作业。如果作业已经存在,则作业已经运行(不过,您可能需要仔细检查以确保作业没有失败)。

    【讨论】:

    • 谢谢乔丹。我能够从有效凭据成功构建 bq 客户端对象。使用 bq,我能够实现 dosTableExist 函数。
    • 404 也可能意味着由于多种原因资源不存在,而用户会认为该表根本不存在。现在工作?可能是。经过 N 年的“工作”尝试发现错误。
    • 如果你已经有一个实例化的客户端,有一个.exists() 方法。请在stackoverflow.com/a/47884257/92471查看我的回答
    • “如果你想知道bq是从哪里来的”,这里的链接好像很空?
    【解决方案3】:

    享受:

    def doesTableExist(bigquery, project_id, dataset_id, table_id):
        try:
            bigquery.tables().get(
                projectId=project_id, 
                datasetId=dataset_id,
                tableId=table_id).execute()
            return True
        except Exception as err:
            if err.resp.status != 404:
                raise
            return False
    

    异常中有一个编辑。

    【讨论】:

      【解决方案4】:

      my_bigquerygoogle.cloud.bigquery.Client 类的一个实例(已通过身份验证并与项目相关联):

      my_bigquery.dataset(dataset_name).table(table_name).exists()  # returns boolean
      

      它通过 GET 请求执行 API 调用以测试表是否存在

      来源:https://googlecloudplatform.github.io/google-cloud-python/0.24.0/bigquery-table.html#google.cloud.bigquery.table.Table.exists

      它适用于我使用 0.27 的 Google Bigquery Python 模块

      【讨论】:

      【解决方案5】:

      内联 SQL 替代方案

      tarheel 的回答可能是目前最正确的

      但我正在考虑 Ivan 上面的评论,即“404 也可能意味着由于多种原因资源不存在”,所以这里有一个解决方案,应该始终成功运行元数据查询并返回结果。

      这不是最快的,因为它总是要运行查询,bigquery 对小查询有开销

      我之前看到的一个技巧是查询information_schema 以获取(表)对象,并将union 查询为确保即使对象没有返回记录也始终返回的假查询。还有一个LIMIT 1 和一个排序,以确保返回的单个记录代表该表(如果它确实存在)。请参阅下面代码中的 SQL。

      • 尽管文档声称 Bigquery 标准 SQL 符合 ISO 标准,但它们不支持 information_schema,但它们确实有 __table_summary__
      • 数据集是必需的,因为如果不指定数据集就无法查询__table_summary__
      • 数据集不是 SQL 中的参数,因为您无法在没有 sql 注入问题的情况下参数化对象名称(除了神奇的_TABLE_SUFFIX,请参阅https://cloud.google.com/bigquery/docs/querying-wildcard-tables
      #!/usr/bin/env python
      """
      Inline SQL way to check a table exists in Bigquery
      
      e.g.
      print(table_exists(dataset_name='<dataset_goes_here>', table_name='<real_table_name'))
      True
      
      print(table_exists(dataset_name='<dataset_goes_here>', table_name='imaginary_table_name'))
      False
      """
      from __future__ import print_function
      from google.cloud import bigquery
      
      
      def table_exists(dataset_name, table_name):
          client = bigquery.Client()
          query = """
              SELECT table_exists FROM
              (
                SELECT true as table_exists, 1 as ordering
                FROM __TABLES_SUMMARY__ WHERE table_id = @table_name
                UNION ALL
                SELECT false as table_exists, 2 as ordering
              ) ORDER by ordering LIMIT 1"""
          query_params = [bigquery.ScalarQueryParameter('table_name', 'STRING', table_name)]
          job_config = bigquery.QueryJobConfig()
          job_config.query_parameters = query_params
      
          if dataset_name is not None:
              dataset_ref = client.dataset(dataset_name)
              job_config.default_dataset = dataset_ref
      
          query_job = client.query(
              query,
              job_config=job_config
          )
      
          results = query_job.result()
          for row in results:
              # There is only one row because LIMIT 1 in the SQL
              return row.table_exists
      

      【讨论】:

        【解决方案6】:

        您现在可以使用exists() 检查数据集是否与表相同 BigQuery exist documentation

        【讨论】:

        • 链接不正确。
        • 据我所知,这是用于数据集而不是表。
        猜你喜欢
        • 2017-08-09
        • 1970-01-01
        • 2019-11-25
        • 1970-01-01
        • 1970-01-01
        • 2021-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多