Получение временной таблицы BigQuery «таблица назначения» с использованием Python API

#google-bigquery

#google-bigquery

Вопрос:

Мой вариант использования — создать временную таблицу и загрузить данные из запроса select, а затем извлечь таблицу в виде CSV в облачном хранилище с помощью Python API.

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

это код

     from google.cloud import bigquery
    bq_key = settings.BASE_DIR   '/api_keys/storage_bq_admin.json'
    bq_client = bigquery.Client.from_service_account_json(bq_key, project='my-project-id')

    query = """
            EXECUTE IMMEDIATE
      "CREATE TEMP TABLE segusers1 (user_id STRING, client_id STRING, inserted_at TIMESTAMP) AS SELECT user_id,client_id,inserted_at FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY inserted_at DESC ) AS top FROM `project-id.prod.users_partition_by_client` WHERE partition_id = 3666 AND client_id = '123456' AND inserted_at > '2020-09-17 00:59:11.461')"
            """
    query_job = bq_client.query(query, job_id="segment_temp_%s" % str(uuid.uuid4()))  # Make an API request.

    results = query_job.result()  # Waits for job to complete.
    bq_job_id = query_job.job_id
    print(query_job.__dict__)
  

query_job возвращает

 {'_retry': <google.api_core.retry.Retry object at 0x7fdc41758748>, '_result': <google.cloud.bigquery.job.QueryJob object at 0x7fdc3ca682e8>, '_exception': None, '_result_set': True, '_polling_thread': None, '_done_callbacks': [], '_properties': {'kind': 'bigquery#job', 'etag': '3uEKLSpG6pZPeLsnzA==', 'id': 'pid-107805:US.segment_temp_3f7e533f-eb64-427f-bbb6-d3e31d78ca56', 'selfLink': 'https://bigquery.googleapis.com/bigquery/v2/projects/pid-107805/jobs/segment_temp_3f7e533f-eb64-427f-bbb6-d3e31d78ca56?location=US', 'user_email': '', 'configuration': {'query': {'query': 'n            EXECUTE IMMEDIATEn      "CREATE TEMP TABLE segusers1 (user_id STRING, client_id STRING, inserted_at TIMESTAMP) AS SELECT user_id,client_id,inserted_at FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY inserted_at DESC ) AS top FROM `pid.prod.users_partition_by_client` WHERE partition_id = 3666 AND client_id = 'cl3666dnx3klmb' AND inserted_at > '2020-09-17 00:59:11.461')"n            ', 'priority': 'INTERACTIVE', 'useLegacySql': False}, 'jobType': 'QUERY'}, 'jobReference': {'projectId': 'pid-107805', 'jobId': 'segment_temp_3f7e533f-eb64-427f-bbb6-d3e31d78ca56', 'location': 'US'}, 'statistics': {'creationTime': 1600359344198.0, 'startTime': 1600359344308.0, 'endTime': 1600359346615.0, 'totalBytesProcessed': '1292600', 'query': {'totalBytesProcessed': '1292600', 'totalBytesBilled': '10485760', 'totalSlotMs': '6637', 'statementType': 'SCRIPT'}, 'totalSlotMs': '6637', 'numChildJobs': '1', 'scriptStatistics': {}}, 'status': {'state': 'DONE'}}, '_client': <google.cloud.bigquery.client.Client object at 0x7fdc42448588>, '_completion_lock': <unlocked _thread.lock object at 0x7fdc42355d00>, '_configuration': <google.cloud.bigquery.job.QueryJobConfig object at 0x7fdc423d8fd0>, '_query_results': <google.cloud.bigquery.query._QueryResults object at 0x7fdc42467da0>, '_done_timeout': None, '_transport_timeout': None}
  

из проводника API документа с использованием идентификатора задания

 {
  "kind": "bigquery#job",
  "etag": "3uEKLSpg961G6pZPeA==",
  "id": "pid-107805:US.segment_temp_3f7e533f-eb64-427f-bbb6-d3e31d78ca56",
  "selfLink": "https://content-bigquery.googleapis.com/bigquery/v2/projects/pid-107805/jobs/segment_temp_3f7e533f-eb64-427f-bbb6-d3e31d78ca56?location=US",
  "user_email": "storage-bq-admin@pid-107805.iam.gserviceaccount.com",
  "configuration": {
    "query": {
      "query": "n            EXECUTE IMMEDIATEn      "CREATE TEMP TABLE segusers1 (user_id STRING, client_id STRING, inserted_at TIMESTAMP) AS SELECT user_id,client_id,inserted_at FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY inserted_at DESC ) AS top FROM `pid-107805.prod.users_partition_by_client` WHERE partition_id = 3666 AND client_id = 'cl3666dnx3klmb' AND inserted_at u003e '2020-09-17 00:59:11.461')"n            ",
      "priority": "INTERACTIVE",
      "useLegacySql": false
    },
    "jobType": "QUERY"
  },
  "jobReference": {
    "projectId": "pid-107805",
    "jobId": "segment_temp_3f7e533f-eb64-427f-bbb6-d3e31d78ca56",
    "location": "US"
  },
  "statistics": {
    "creationTime": "1600359344198",
    "startTime": "1600359344308",
    "endTime": "1600359346615",
    "totalBytesProcessed": "1292600",
    "query": {
      "totalBytesProcessed": "1292600",
      "totalBytesBilled": "10485760",
      "totalSlotMs": "6637",
      "statementType": "SCRIPT"
    },
    "totalSlotMs": "6637",
    "numChildJobs": "1",
    "scriptStatistics": {}
  },
  "status": {
    "state": "DONE"
  }
}
  

оба возврата без требуемых сведений о таблице назначения, я полагаю, запрос должен содержать значения datasetId вновь созданной таблицы. Не уверен, чего мне здесь не хватает.

Ответ №1:

Это своего рода злоупотребление НЕМЕДЛЕННЫМ ВЫПОЛНЕНИЕМ и созданием ВРЕМЕННОЙ таблицы в вашем коде.

Если вы удалите оба, ваш запрос станет прямым выбором, например:

     query = """
            SELECT user_id,client_id,inserted_at ...
            """
  

Затем вы сможете найти таблицу назначения в задании, аналогичном:

 {
  "configuration": {
    "jobType": "QUERY", 
    "query": {
      "destinationTable": {     <======== what you're looking for
        "datasetId": "_c53c0a2640dc04748b94ebc5d7193a6976b85fa1", 
        "projectId": "yourProject", 
        "tableId": "anon8b75560af5d60d88fd40befe1371bb83696c86e1"
      }, 
...

  

Комментарии:

1. Это создание обычной таблицы, не так ли? Я пытаюсь создать временную таблицу вместо обычной таблицы, для которой требуются сценарии. Сокращение затрат — основная причина, по которой я выбираю временную таблицу

2. Как эта таблица результатов запроса, так и временная таблица в сценариях находятся во временном наборе данных и имеют продолжительность жизни 24 часа, они ничем не отличаются.