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

此外,每個專案的總處理量也有配額限制。這代表透過 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,並顯示 StorageErrorCode.SCHEMA_MISMATCH_EXTRA_FIELD

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

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

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

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