BigQuery - проверьте, существует ли таблица

У меня есть набор данных в BigQuery. Этот набор данных содержит несколько таблиц.

Я выполняю следующие шаги программным образом с помощью API BigQuery:

  • Запрос таблиц в наборе данных. Поскольку мой ответ слишком велик, я включаю параметр allowLargeResults и перенаправляю свой ответ на таблицу назначения.

  • Затем я экспортирую данные из таблицы адресатов в ведро GCS.

Требования:

  • Предположим, что мой процесс завершился неудачно на шаге 2, я хотел бы повторно запустить этот шаг.

  • Но перед повторным запуском я хотел бы проверить/проверить, что определенная таблица назначения с именем "xyz" уже существует в наборе данных.

  • Если он существует, я хотел бы повторно запустить шаг 2.

  • Если этого не существует, я хотел бы сделать foo.

Как я могу это сделать?

Спасибо заранее.

Ответ 1

Вот фрагмент кода Python, который скажет, существует ли таблица (удаляя ее в процессе - осторожно!):

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_client здесь: http://code.google.com/p/bigquery-e2e/source/browse/samples/ch12/auth.py

В общем, если вы используете это для проверки того, следует ли запускать задание, которое изменит таблицу, может быть хорошей идеей просто выполнить задание в любом случае и использовать WRITE_TRUNCATE в качестве расположения записи.

Другим подходом может быть создание предсказуемого идентификатора задания и повторное выполнение задания с этим идентификатором. Если задание уже существует, задание уже выполнено (однако вы можете проверить его еще раз, чтобы убедиться, что задание не провалилось).

Ответ 2

Решение Alex F работает на v0.27, но не будет работать на более поздних версиях. Для перехода на 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)

Ответ 3

Enjoy:

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_bigquery является экземпляром класса google.cloud.bigquery.Client (уже аутентифицированного и связанного с проектом):

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

Он выполняет вызов API для проверки существования таблицы с помощью запроса GET

Источник: 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, пожалуй, самый правильный на данный момент

но я рассматривал комментарий Ивана выше, что "404 может также означать, что ресурс не существует по ряду причин", так что вот решение, которое всегда должно успешно выполнять запрос метаданных и возвращать результат.

Это не самый быстрый, потому что он всегда должен выполнить запрос, bigquery имеет накладные расходы для небольших запросов

Уловка, которую я видел ранее, состоит в том, чтобы запросить information_schema для (табличного) объекта и union его с поддельным запросом, который гарантирует, что запись всегда возвращается, даже если объект этого не делает. Существует также LIMIT 1 и порядок, чтобы гарантировать, что одна возвращенная запись представляет таблицу, если она существует. Смотрите SQL в коде ниже.

  • Несмотря на заявления doc о том, что стандарт SQL Bigquery совместим с 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.