將資料匯出至 Spanner (反向 ETL)
本文說明如何設定從 BigQuery 到 Spanner 的反向擷取、轉換及載入 (反向 ETL) 工作流程。您可以使用 EXPORT DATA 陳述式,從 BigQuery 資料來源 (包括 Iceberg 資料表) 匯出資料至 Spanner 資料表。
這項反向 ETL 工作流程結合了 BigQuery 的分析功能,以及 Spanner 的低延遲和高總處理量特性。這個工作流程可讓您將資料提供給應用程式使用者,而不會超出 BigQuery 的配額和限制。
事前準備
建立 Spanner 資料庫,包括接收匯出資料的資料表。
授予身分與存取權管理 (IAM) 角色,讓使用者擁有執行本文各項工作所需的權限。
建立企業或更高等級的預留項目。 將資料一次性匯出至 Spanner 時,您可以將基準運算單元容量設為零,並啟用自動調度資源,藉此降低 BigQuery 運算成本。
必要的角色
如要取得將 BigQuery 資料匯出至 Spanner 所需的權限,請要求管理員在專案中授予您下列 IAM 角色:
-
從 BigQuery 資料表匯出資料:
BigQuery 資料檢視者 (
roles/bigquery.dataViewer) -
執行擷取作業:
BigQuery 使用者 (
roles/bigquery.user) -
檢查 Spanner 執行個體的參數:
Cloud Spanner 檢視者 (
roles/spanner.viewer) -
將資料寫入 Spanner 資料表:
Cloud Spanner 資料庫使用者 (
roles/spanner.databaseUser)
如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。
限制
Assured Workloads 不支援這項功能。
下列 BigQuery 資料類型在 Spanner 中沒有對應項目,因此不支援:
| Spanner 資料庫方言 | 不支援的 BigQuery 類型 |
|---|---|
| 所有方言 |
|
| GoogleSQL |
|
匯出資料列的大小上限為 1 MiB。
Spanner 會在匯出期間強制執行參照完整性。 如果目標資料表是另一個資料表的子項 (INTERLEAVE IN PARENT),或目標資料表有外鍵限制,系統會在匯出期間驗證外鍵和父項鍵。如果匯出的資料列寫入的資料表具有 INTERLEAVE IN PARENT,但父項資料列不存在,匯出作業就會失敗,並顯示「Parent row is missing. 無法寫入資料列」錯誤。如果匯出的資料列寫入的資料表含有外鍵限制,且參照的鍵不存在,匯出作業就會失敗,並顯示「違反外鍵限制」錯誤。匯出至多個資料表時,建議您依序匯出,確保匯出作業維持參照完整性。這通常表示先匯出父項資料表和外鍵參照的資料表,再匯出參照這些資料表的資料表。
如果匯出目標資料表有外鍵限制,或是另一個資料表的子項 (INTERLEAVE IN PARENT),則必須先填入父項資料表,再匯出子項資料表,且父項資料表應包含所有對應的鍵。如果父項資料表沒有完整的相關鍵集,嘗試匯出子項資料表就會失敗。
BigQuery 工作 (例如擷取至 Spanner 的工作) 的最長執行時間為 6 小時。如要瞭解如何最佳化大型擷取工作,請參閱「匯出最佳化」。或者,您也可以考慮將輸入內容分割成個別資料區塊,然後以個別擷取工作匯出。
只有 BigQuery Enterprise 或 Enterprise Plus 版本支援匯出至 Spanner。不支援 BigQuery Standard 版和隨選運算。
您無法使用持續查詢,將資料匯出至具有自動產生主鍵的 Spanner 資料表。
您無法使用連續查詢,將資料匯出至 PostgreSQL 方言資料庫中的 Spanner 資料表。
使用連續查詢匯出至 Spanner 資料表時,請務必選擇與 BigQuery 資料表中單調遞增整數不相符的主鍵。否則可能會導致匯出作業發生效能問題。如要瞭解 Spanner 中的主鍵,以及如何減輕這些效能問題,請參閱「選擇主鍵」。
使用「spanner_options」選項設定匯出作業
您可以使用 spanner_options 選項指定目標 Spanner 資料庫和資料表。設定會以 JSON 字串的形式表示,如下列範例所示:
EXPORT DATA OPTIONS( uri="https://spanner.googleapis.com/projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID", format='CLOUD_SPANNER', spanner_options = """{ "table": "TABLE_NAME", "change_timestamp_column": "CHANGE_TIMESTAMP", "priority": "PRIORITY", "tag": "TAG", }""" )
更改下列內容:
PROJECT_ID: Google Cloud 專案的名稱。INSTANCE_ID:資料庫執行個體的名稱。DATABASE_ID:資料庫名稱。TABLE_NAME:現有目標資料表的名稱。CHANGE_TIMESTAMP:目的地 Spanner 資料表中的TIMESTAMP型別資料欄名稱。這個選項會在匯出期間使用,追蹤最新列更新的時間戳記。指定這個選項後,匯出作業會先讀取 Spanner 資料表中的資料列,確保只寫入最新的資料列更新。執行持續匯出時,建議指定TIMESTAMP類型資料欄,因為相同主鍵的資料列變更順序非常重要。PRIORITY(選用): 寫入要求的優先順序。允許的值:LOW、MEDIUM、HIGH。預設值:MEDIUM。TAG(選用): 要求標記 ,有助於在 Spanner 監控中識別匯出工具流量。 預設值為bq_export。
匯出查詢的規定
如要將查詢結果匯出至 Spanner,結果必須符合下列條件:
- 結果集中的所有資料欄都必須存在於目的地資料表中,且類型必須相符或可轉換。
- 結果集必須包含目的地資料表的所有
NOT NULL欄。 - 資料欄值不得超過資料表中的 Spanner 資料大小限制。
- 匯出至 Spanner 前,必須將所有不支援的資料欄類型轉換為支援的類型。
類型轉換
為方便使用,Spanner 匯出工具會自動套用下列型別轉換:
| BigQuery 類型 | 扳手類型 |
|---|---|
| BIGNUMERIC | NUMERIC (僅限 PostgreSQL 方言) |
| FLOAT64 | FLOAT32 |
| BYTES | PROTO |
| INT64 | ENUM |
匯出資料
您可以使用 EXPORT DATA 陳述式,將資料從 BigQuery 資料表匯出至 Spanner 資料表。
下列範例會從名為 mydataset.table1 的資料表匯出所選欄位:
EXPORT DATA OPTIONS ( uri="https://spanner.googleapis.com/projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID", format='CLOUD_SPANNER', spanner_options="""{ "table": "TABLE_NAME" }""" ) AS SELECT * FROM mydataset.table1;
更改下列內容:
PROJECT_ID: Google Cloud 專案名稱INSTANCE_ID:資料庫執行個體的名稱DATABASE_ID:資料庫名稱TABLE_NAME:現有目的地資料表的名稱
匯出具有相同 rowkey 值的多個結果
匯出含有多個相同 rowkey 值的資料列時,寫入 Spanner 的值會位於同一個 Spanner 資料列。匯出作業產生的 Spanner 資料列集只會包含單一相符的 BigQuery 資料列 (無法保證是哪一個)。
持續匯出
如要持續處理匯出查詢,請參閱建立持續查詢的操作說明和範例程式碼。
匯出最佳化
如要盡量縮短從 BigQuery 匯出記錄至 Spanner 的時間,可以嘗試下列做法:
增加 Spanner 目的地執行個體中的節點數量。在匯出作業的初期階段,增加執行個體中的節點數量可能不會立即提高匯出輸送量。Spanner 執行以負載為準的分割時,可能會稍微延遲。依負載分割可提高匯出作業的處理量,並維持穩定。使用
EXPORT DATA陳述式批次處理資料,以最佳化寫入 Spanner 的作業。詳情請參閱「成效總覽」。在
spanner_options中指定HIGH優先順序。如果 Spanner 執行個體已啟用自動調度資源功能,設定HIGH優先順序有助於確保 CPU 使用率達到觸發調度資源的必要門檻。這樣一來,自動調度器就能根據匯出負載新增運算資源,進而提升整體匯出輸送量。以下範例顯示設為
HIGH優先順序的 Spanner 匯出指令:EXPORT DATA OPTIONS ( uri="https://spanner.googleapis.com/projects/
PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID", format='CLOUD_SPANNER', spanner_options="""{ "table": "TABLE_NAME", "priority": "HIGH" }""" )避免排序查詢結果。如果結果集包含所有主鍵欄,匯出工具會自動排序目的地表格的主鍵,以簡化寫入作業並減少爭用。
如果目的地資料表的主鍵包含產生的資料欄,請將產生的資料欄運算式新增至查詢,確保匯出的資料經過適當排序和批次處理。
舉例來說,在下列 Spanner 結構定義中,
SaleYear和SaleMonth是構成 Spanner 主鍵開頭的產生資料欄:CREATE TABLE Sales ( SaleId STRING(36) NOT NULL, ProductId INT64 NOT NULL, SaleTimestamp TIMESTAMP NOT NULL, Amount FLOAT64, -- Generated columns SaleYear INT64 AS (EXTRACT(YEAR FROM SaleTimestamp)) STORED, SaleMonth INT64 AS (EXTRACT(MONTH FROM SaleTimestamp)) STORED, ) PRIMARY KEY (SaleYear, SaleMonth, SaleId);
從 BigQuery 匯出資料至 Spanner 資料表時,如果主鍵使用產生的資料欄,建議 (但非必要) 在
EXPORT DATA查詢中加入這些產生資料欄的運算式。這樣 BigQuery 就能正確預先排序資料,這對有效率地批次處理資料並寫入 Spanner 至關重要。EXPORT DATA陳述式中產生的資料欄值不會在 Spanner 中提交,因為這些值是由 Spanner 自動產生,但會用於最佳化匯出作業。下列範例會將資料匯出至 Spanner
Sales資料表,該資料表的主鍵使用產生的資料欄。為提升寫入效能,查詢會包含與產生的SaleYear和SaleMonth資料欄相符的EXTRACT運算式,讓 BigQuery 在匯出資料前預先排序:EXPORT DATA OPTIONS ( uri="https://spanner.googleapis.com/projects/
PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID", format='CLOUD_SPANNER', spanner_options="""{ "table": "Sales" }""" ) AS SELECT s.SaleId, s.ProductId, s.SaleTimestamp, s.Amount, -- Add expressions that match the generated columns in the Spanner PK EXTRACT(YEAR FROM s.SaleTimestamp) AS SaleYear, EXTRACT(MONTH FROM s.SaleTimestamp) AS SaleMonth FROM my_dataset.sales_export AS s;為避免工作長時間執行,請依分區匯出資料。使用分區鍵 (例如查詢中的時間戳記) 將 BigQuery 資料分片:
EXPORT DATA OPTIONS ( uri="https://spanner.googleapis.com/projects/
PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID", format='CLOUD_SPANNER', spanner_options="""{ "table": "TABLE_NAME", "priority": "MEDIUM" }""" ) AS SELECT * FROM 'mydataset.table1' d WHERE d.timestamp >= TIMESTAMP '2025-08-28T00:00:00Z' AND d.timestamp < TIMESTAMP '2025-08-29T00:00:00Z';這樣查詢就能在 6 小時的工作執行時間內完成。如要進一步瞭解這些限制,請參閱查詢工作限制。
如要提升資料載入效能,請在匯入資料的 Spanner 表格中捨棄索引。然後在匯入完成後重新建立。
建議您先從一個 Spanner 節點 (1000 個處理器單元) 和最少的 BigQuery 預留時段開始。例如 100 個運算單元,或 0 個基準運算單元 (搭配自動調度資源)。如果匯出資料量小於 100 GB,這項設定通常會在 6 小時的工作限制內完成。如要匯出超過 100 GB 的資料,請視需要增加 Spanner 節點和 BigQuery 運算單元預留量,以提高輸送量。每個節點的處理量約為每秒 5 MiB。
定價
使用 EXPORT DATA 陳述式將資料匯出至 Spanner 時,系統會按照 BigQuery 容量運算定價計費。
如要使用持續查詢功能,將資料持續匯出至 Spanner,您必須擁有 BigQuery Enterprise 或 Enterprise Plus 版的運算單元保留項目,以及使用 CONTINUOUS 工作類型的保留項目指派作業。
如果 BigQuery 匯出至 Spanner 的資料跨越區域界線,系統會按照資料擷取費率收費。詳情請參閱 BigQuery 計價方式一文。為避免資料移轉費用,請確保 BigQuery 匯出作業與 Spanner 預設領導者位於相同區域。持續查詢匯出作業不支援跨區域邊界的匯出作業。
匯出資料後,系統會因您在 Spanner 中儲存資料而向您收取費用。詳情請參閱 Spanner 定價。