BigQuery Storage Write API 最佳做法

本文提供使用 BigQuery Storage Write API 的最佳做法。請先閱讀 BigQuery Storage Write API 簡介

限制串流建立頻率

建立串流之前,請先考慮是否可以使用預設串流。在串流情境中,預設串流的配額限制較少,且可比使用應用程式建立的串流更容易調整。如果您使用應用程式建立的串流,請務必先使用每個串流的最大吞吐量,再建立其他串流。例如使用非同步寫入

對於應用程式建立的串流,請避免頻繁呼叫 CreateWriteStream。一般來說,如果每秒的呼叫次數超過 40 到 50 次,API 呼叫的延遲時間就會大幅增加 (超過 25 秒)。請確認應用程式可接受冷啟動,並逐漸增加串流數量,以及限制 CreateWriteStream 呼叫的頻率。您也可以設定較長的期限,等待呼叫完成,以免因 DeadlineExceeded 錯誤而失敗。CreateWriteStream 呼叫的最高速率也有長期配額。建立串流是耗用大量資源的程序,因此減少串流建立率並充分利用現有串流,是避免超出此限制的最佳做法。

連線集區管理

AppendRows 方法會建立與串流的雙向連線。您可以在預設串流上開啟多個連線,但在應用程式建立的串流上只能開啟單一有效連線。

使用預設串流時,您可以使用 Storage Write API 多工處理功能,透過共用連線寫入多個目的地資料表。多重連線集區,以提升資源的處理量和使用率。如果工作流程有超過 20 個並行連線,建議您使用多重處理。多重處理可在 Java 和 Go 中使用。如需 Java 實作詳細資訊,請參閱「使用多重處理」。如需 Go 實作詳細資訊,請參閱「連線共用 (多重化)」一文。如果您使用含有至少一次語義的 Beam 連接器,可以透過 UseStorageApiConnectionPool 啟用多重訊號傳輸。Dataproc Spark 連接器預設會啟用多重處理功能。

為獲得最佳效能,請盡可能使用一個連線來寫入大量資料。請勿將單一連線用於單一寫入作業,或開啟及關閉用於許多小型寫入作業的串流。

每個專案同時可開啟的並行連線數量有配額限制。超過上限時,對 AppendRows 的呼叫會失敗。不過,您可以增加並行連線的配額,這通常不會成為限制擴充的因素。

每次呼叫 AppendRows 都會建立新的資料寫入器物件。因此,使用應用程式建立的串流時,連線數量會對應到已建立的串流數量。一般而言,單一連線可支援至少 1MBps 的傳輸量。上限取決於多項因素,例如網路頻寬、資料結構定義和伺服器負載,但可能會超過 10MBps。

每個專案的總處理量也有配額。這項指標代表透過 Storage Write API 服務的所有連線,每秒傳輸的位元組數。如果專案超出這個配額,您可以要求調整配額。通常會以相同的比率提高相關配額,例如並發連線配額。

管理串流偏移量,實現「僅限一次」語意

Storage Write API 只允許寫入串流的目前結尾,而該結尾會隨著資料附加而移動。串流中目前的位置會指定為從串流開頭算起的偏移量。

當您寫入應用程式建立的串流時,可以指定串流偏移量,以便實現一次性寫入語意。

指定偏移量時,寫入作業會變成不變量,因此在發生網路錯誤或伺服器未回應時,可以安全地重試。處理下列與偏移相關的錯誤:

  • ALREADY_EXISTS (StorageErrorCode.OFFSET_ALREADY_EXISTS):資料列已寫入。您可以放心忽略這項錯誤。
  • OUT_OF_RANGE (StorageErrorCode.OFFSET_OUT_OF_RANGE):先前的寫入作業失敗。從上次成功寫入的位置重試。

請注意,如果您設定錯誤的偏移值,也會發生這些錯誤,因此請務必謹慎管理偏移值。

使用串流偏移值前,請先考慮是否需要精確一次語義。舉例來說,如果上游資料管道只保證至少一次寫入,或是您可以在資料擷取後輕鬆偵測重複項目,那麼您可能不需要精確一次寫入。在這種情況下,建議您使用預設串流,因為不需要追蹤資料列偏移。

不要在 AppendRows 通話中封鎖

AppendRows 方法為非同步方法。您可以傳送一系列寫入作業,而不會因個別寫入作業的回應而阻斷。雙向連線上的回應訊息會按照排入佇列的順序傳送。如要獲得最高的處理量,請呼叫 AppendRows,但不要封鎖等待回應的動作。

處理結構定義更新

在資料串流情境中,資料表結構定義通常會在串流管道之外進行管理。結構定義通常會隨著時間演進,例如新增可為空值的欄位。完善的管道必須處理非頻道結構定義更新。

Storage Write API 支援下列資料表結構定義:

  • 第一個寫入要求會包含結構定義。
  • 您可以將每個資料列傳送為二進位通訊協定緩衝區。BigQuery 會將資料對應至結構定義。
  • 您可以省略可為空值的欄位,但不得加入目前結構定義中不存在的任何欄位。如果您傳送包含額外欄位的資料列,Storage Write API 會傳回含有 StorageErrorCode.SCHEMA_MISMATCH_EXTRA_FIELDStorageError

如果您想在酬載中傳送新欄位,請先在 BigQuery 中更新資料表結構定義。Storage Write API 會在短時間 (約幾分鐘) 內偵測到結構描述變更。當儲存空間寫入 API 偵測到結構定義變更時,AppendRowsResponse 回應訊息會包含 TableSchema 物件,說明新的結構定義。

如要使用更新後的結構定義傳送資料,您必須關閉現有的連線,並使用新的結構定義開啟新的連線。

Java 用戶端。Java 用戶端程式庫透過 JsonStreamWriter 類別,提供一些額外的結構定義更新功能。結構定義更新後,JsonStreamWriter 會自動重新連線至更新後的結構定義。您不需要明確關閉及重新開啟連線。如要透過程式輔助檢查結構定義變更,請在 append 方法完成後呼叫 AppendRowsResponse.hasUpdatedSchema

您也可以設定 JsonStreamWriter,讓系統忽略輸入資料中的不明欄位。如要設定這項行為,請呼叫 setIgnoreUnknownFields。這項行為類似於使用舊版 tabledata.insertAll API 時的 ignoreUnknownValues 選項。不過,由於未知欄位會悄悄捨棄,因此可能會導致資料遺失。