簡體   English   中英

將查詢結果保存在 Cloud Storage 中的 BigQuery 表中

[英]Save the result of a query in a BigQuery Table, in Cloud Storage

我想知道將 Google BigQuery 表查詢結果存儲到 Google Cloud 存儲的最佳方式是什么。 我的代碼目前正在某些 Jupyter Notebook 中運行(在 Vertex AI Workbench 中,與 BigQuery 數據源和 Cloud Storage 目標相同的項目)如下所示:

# CELL 1 OF 2

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

# The query string can vary:
query_string = """
        SELECT *  
        FROM `my_project-name.my_db.my_table` 
        LIMIT 2000000
        """

dataframe = (
    bqclient.query(query_string)
    .result()
    .to_dataframe(
        create_bqstorage_client=True,
    )
)
print("Dataframe shape: ", dataframe.shape)

# CELL 2 OF 2:

import pandas as pd
dataframe.to_csv('gs://my_bucket/test_file.csv', index=False)

此代碼大約需要 7.5 分鍾才能成功完成。

有沒有更優化的方法來實現上面所做的? (這意味着更快,但也許還有其他可以改進的地方)。

一些附加說明:

  1. 我想“通過 Jupyter Notebook”(在 Vertex AI Workbench 中)運行它,因為有時必須進行一些數據預處理或特殊過濾,這無法通過 SQL 查詢輕松完成。
  2. 對於代碼的第一部分,我丟棄了pandas.read_gbq ,因為它在(實驗性地)“存儲為 CSV 並回讀”時給我一些奇怪的 EOF 錯誤。
  3. 直覺上,我會將優化工作集中在代碼的后半部分 ( CELL 2 OF 2 ),因為第一部分是從Google 官方文檔中借用的 我試過這個但它不起作用,但是在同一個線程中這個選項工作正常。
  4. 這段代碼很可能會包含在一些 Docker 圖像中,因此必須使用“盡可能少的庫”。

謝謝你。

使用EXPORT DATA語句:


EXPORT DATA OPTIONS(
  uri='gs://bucket/folder/*.csv',
  format='CSV',
  overwrite=true,
  header=true,
  field_delimiter=';') AS
SELECT *
FROM `my_project.my_db.my_table`
LIMIT 2000000

  • URI 中的 * 允許將一個表導出為多個表。 這僅在導出表大於 1GB 時才重要( 參見此處

通過命令行或在您的 python 腳本中直接在 BQ 控制台中執行。

from google.cloud import bigquery

client = bigquery.Client()

query_job = client.query(
    """
    EXPORT DATA OPTIONS(
      uri='gs://bucket/folder/*.csv',
      format='CSV',
      overwrite=true,
      header=true,
      field_delimiter=';') AS
    SELECT *
    FROM `my_project.my_db.my_table`
    LIMIT 2000000
  """
)

results = query_job.result()  # Waits for job to complete.

關於LIMIT的注釋:請注意, LIMIT不會減少在非集群表中讀取的數據量。 只有返回的內容。 見這里

經過一些實驗,我想我已經為我的原始帖子找到了解決方案。 首先,更新的代碼:

import pandas as pd  # Just one library is imported this time

# This SQL query can vary, modify it to match your needs
query_string = """
SELECT *
FROM `my_project.my_db.my_table`
LIMIT 2000000
"""

# One liner to query BigQuery data.
downloaded_dataframe = pd.read_gbq(query_string, dialect='standard', use_bqstorage_api=True)

# Data processing (OPTIONAL, modify it to match your needs)
# I won't do anything this time, just upload the previously queried data

# Data store in GCS
downloaded_dataframe.to_csv('gs://my_bucket/uploaded_data.csv', index=False)

最后的一些注意事項:

  1. 我沒有對處理速度與 BigQuery 表中存在的行數進行“深入研究”,但是我看到更新代碼和原始查詢的處理時間現在需要 ~6 分鍾; 暫時就夠了。 因此,這個答案可能還有進一步改進的空間,但比原來的情況要好。
  2. 我在原始帖子中提到的 EOF 錯誤是: ParserError: Error tokenizing data. C error: EOF inside string starting at row 70198 ParserError: Error tokenizing data. C error: EOF inside string starting at row 70198 最后我意識到它與pandas_gbq function 沒有任何關系,而是與“我如何保存數據”有關。 看,我正在“實驗性地”將 .csv 文件存儲在 Vertex AI Workbench 本地存儲中,然后將其下載到我的本地設備,當我嘗試從我的本地設備打開該數據時,我不斷遇到該錯誤,但沒有得到從 Cloud Storage 下載 .csv 數據時也是如此……為什么? 好吧,如果您在“生成”后(即幾秒鍾后)“非常快”地從 Vertex AI Workbench 本地存儲下載 .csv 數據,數據仍然不完整,但它不會提供任何信息錯誤或警告消息:它只會“讓您開始下載”。 出於這個原因,我認為將數據導出到 Cloud Storage,然后從那里安全下載會更安全。 這種行為在大文件上更為明顯(即我自己生成的文件,大小約為 3.1GB)。

希望這可以幫助。

謝謝你。

在此鏈接中,您將找到完成此任務的方法: https://cloud.google.com/bigquery/docs/samples/bigquery-extract-table?hl=en

雖然,您需要注意一些要點。

  • 這只是一個摘錄,但如果你想做一些轉換,你可以使用 Dataflow 或 Composer,最后一個允許你使用 BQ 作業使用 SQL 轉換來調整你想要的東西。 另一方面,Dataflow 使用 python 來處理代碼並創建作業。

  • 此外,您可能還需要關注您的 bq 表性能、分區和集群,詳細信息https://cloud.google.com/bigquery/docs/clustered-tables 我還注意到您正在使用limit語句,這不會對您的性能產生影響,因為此 BQ 是柱狀的,因此您仍在掃描所有列和所有數據。

片段:

# from google.cloud import bigquery
# client = bigquery.Client()
# bucket_name = 'my-bucket'
project = "bigquery-public-data"
dataset_id = "samples"
table_id = "shakespeare"

destination_uri = "gs://{}/{}".format(bucket_name, "shakespeare.csv")
dataset_ref = bigquery.DatasetReference(project, dataset_id)
table_ref = dataset_ref.table(table_id)

extract_job = client.extract_table(
    table_ref,
    destination_uri,
    # Location must match that of the source table.
    location="US",
)  # API request
extract_job.result()  # Waits for job to complete.

print(
    "Exported {}:{}.{} to {}".format(project, dataset_id, table_id, destination_uri)
)

希望這可以幫到你:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM