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_FIELD
的StorageError
,並顯示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
選項類似。不過,由於系統會自動捨棄不明欄位,因此可能會導致資料意外遺失。