本文說明如何使用舊版 tabledata.insertAll
方法,將資料以串流方式傳入 BigQuery。
對於新專案,建議使用 BigQuery Storage Write API,而不要使用 tabledata.insertAll
方法。Storage Write API 的定價較低且功能齊全 (包括單次傳送語意),如果您要將現有專案從 tabledata.insertAll
方法遷移至 Storage Write API,建議選取預設串流。tabledata.insertAll
方法仍完全受支援。
事前準備
確認您具備目的地資料表所屬資料集的寫入權限。除非您使用範本資料表,否則該資料表在開始寫入資料之前就必須存在。如要進一步瞭解範本資料表,請參閱使用範本資料表自動建立資料表。
查看串流資料的配額政策。
-
Make sure that billing is enabled for your Google Cloud project.
授予身分與存取權管理 (IAM) 角色,讓使用者擁有執行本文件各項工作所需的權限。
免費方案並不支援資料串流功能。如果不啟用計費功能,當您嘗試進行資料串流作業時,系統會顯示下列錯誤訊息:BigQuery: Streaming insert is not allowed in the free tier.
所需權限
如要將資料以串流方式傳入 BigQuery,您需要下列 IAM 權限:
bigquery.tables.updateData
(可將資料插入表格)bigquery.tables.get
(可取得資料表中繼資料)bigquery.datasets.get
(可取得資料集中繼資料)bigquery.tables.create
(如果您使用範本資料表自動建立資料表,則為必要目錄)
下列每個預先定義的 IAM 角色都包含將資料串流至 BigQuery 時所需的權限:
roles/bigquery.dataEditor
roles/bigquery.dataOwner
roles/bigquery.admin
如要進一步瞭解 BigQuery 中的 IAM 角色和權限,請參閱預先定義的角色和權限一文。
將資料串流至 BigQuery
C#
在試行這個範例之前,請先按照 BigQuery 快速入門導覽課程:使用用戶端程式庫中的 C# 設定說明進行操作。詳情請參閱 BigQuery C# API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。
Go
在試行這個範例之前,請先按照 BigQuery 快速入門導覽課程:使用用戶端程式庫中的 Go 設定說明進行操作。詳情請參閱 BigQuery Go API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。
Java
在試行這個範例之前,請先按照 BigQuery 快速入門導覽課程:使用用戶端程式庫中的 Java 設定說明進行操作。詳情請參閱 BigQuery Java API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。
Node.js
在試行這個範例之前,請先按照 BigQuery 快速入門導覽課程:使用用戶端程式庫中的 Node.js 設定說明進行操作。詳情請參閱 BigQuery Node.js API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。
PHP
在試行這個範例之前,請先按照 BigQuery 快速入門導覽課程:使用用戶端程式庫中的 PHP 設定說明進行操作。詳情請參閱 BigQuery PHP API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。
Python
在試行這個範例之前,請先按照 BigQuery 快速入門導覽課程:使用用戶端程式庫中的 Python 設定說明進行操作。詳情請參閱 BigQuery Python API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。
Ruby
在試行這個範例之前,請先按照 BigQuery 快速入門導覽課程:使用用戶端程式庫中的 Ruby 設定說明進行操作。詳情請參閱 BigQuery Ruby API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。
插入資料列時,不需要在 insertID
欄位中填入資料。
以下範例說明如何在串流時,避免為每個資料列傳送 insertID
。
Java
在試行這個範例之前,請先按照 BigQuery 快速入門導覽課程:使用用戶端程式庫中的 Java 設定說明進行操作。詳情請參閱 BigQuery Java API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。
Python
在試行這個範例之前,請先按照 BigQuery 快速入門導覽課程:使用用戶端程式庫中的 Python 設定說明進行操作。詳情請參閱 BigQuery Python API 參考說明文件。
如要向 BigQuery 進行驗證,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。
傳送日期和時間資料
如果是日期和時間欄位,請在 tabledata.insertAll
方法中將資料格式化,如下所示:
類型 | 格式 |
---|---|
DATE |
採用 "YYYY-MM-DD" |
DATETIME |
採用 "YYYY-MM-DD [HH:MM:SS]" |
TIME |
採用 "HH:MM:SS" |
TIMESTAMP |
自 1970 年 1 月 1 日 (Unix 紀元) 起算的秒數,或 "YYYY-MM-DD HH:MM[:SS]" 格式的字串 |
傳送範圍資料
如為 RANGE<T>
類型的欄位,請在 tabledata.insertAll
方法中將資料格式設為 JSON 物件,並包含 start
和 end
兩個欄位。start
和 end
欄位的值為 NULL 或留空,代表無界限。
這些欄位必須採用相同的支援 JSON 格式 (類型為 T
),其中 T
可以是 DATE
、DATETIME
和 TIMESTAMP
其中之一。
在下列範例中,f_range_date
欄位代表資料表中的 RANGE<DATE>
資料欄。使用 tabledata.insertAll
API,即可在這個資料欄中插入資料列。
{
"f_range_date": {
"start": "1970-01-02",
"end": null
}
}
串流資料可用性
BigQuery 成功確認 tabledata.insertAll
要求後,您就能立即使用 GoogleSQL 查詢,即時分析資料。
最近以串流方式傳入擷取時間分區資料表的資料列,在 _PARTITIONTIME
虛擬資料欄的值暫時為 NULL。對於這類資料列,BigQuery 會在背景中指派 PARTITIONTIME
資料欄的最終非空值,通常會在幾分鐘內完成。在極少數情況下,這項作業最多可能需要 90 分鐘。
最近串流的資料列可能無法用於複製表格,通常會持續幾分鐘。在極少數情況下,這項作業最多可能需要 90 分鐘的時間。如要查看資料表副本是否有資料,請檢查名為 streamingBuffer
的區段的 tables.get
回應。如果缺少 streamingBuffer
部分,則代表您的資料處於可複製的狀態。您也可以使用 streamingBuffer.oldestEntryTime
欄位,識別串流緩衝區中的記錄存續時間。
盡可能清除重複的功能
為插入的資料列提供 insertId
時,BigQuery 會使用這個 ID,盡可能地在最多一分鐘內刪除重複資料。也就是說,如果您在該時間範圍內,將同一個資料列和同一個 insertId
多次串流至同一個資料表,BigQuery 可能會刪除該資料列的重複項目,只保留其中一個。
系統會預期具有相同 insertId
的資料列也相同。如果兩個資料列的 insertId
相同,BigQuery 會保留哪個資料列則不確定。
一般來說,重複資料刪除功能適用於分散式系統中的重試情境,因為在某些錯誤情況下 (例如系統與 BigQuery 之間的網路發生錯誤,或是 BigQuery 發生內部錯誤),無法確定串流資料插入作業的狀態。如果重試插入作業,請對同一組資料列使用相同的 insertId
,BigQuery 就會嘗試刪除重複資料。詳情請參閱「排解串流資料插入的相關問題」。
BigQuery 提供的重複資料刪除功能會盡力執行,但不應做為確保資料中沒有重複項目的機制。此外,為確保資料的可靠性和可用性,BigQuery 可能隨時降低盡量去重複的品質。
如果您對資料有嚴格的重複資料刪除要求,可改為使用支援交易作業的 Google Cloud Datastore 服務。
停用盡可能清除重複的功能
您可以透過不在每個插入的資料列中填入 insertId
欄位來停用盡可能清除重複的功能。建議使用這種方式插入資料。
Apache Beam 和 Dataflow
如要使用 Apache Beam 的 Java BigQuery I/O 連接器停用盡量去重複功能,請使用 ignoreInsertIds()
方法。
手動移除重複內容
為確保串流完成後沒有重複的資料列,請使用下列手動程序:
- 在資料表結構定義中加入
insertId
做為資料欄,並在每列的資料中加入insertId
值。 - 在串流作業停止後,執行下列查詢以檢查是否有重複內容:
假如結果大於 1,表示有重複的項目。#standardSQL SELECT MAX(count) FROM( SELECT ID_COLUMN, count(*) as count FROM `TABLE_NAME` GROUP BY ID_COLUMN)
- 如要移除重複項目,請執行下列查詢。指定目標資料表、允許大型結果,並停用結果扁平化。
#standardSQL SELECT * EXCEPT(row_number) FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY ID_COLUMN) row_number FROM `TABLE_NAME`) WHERE row_number = 1
以下是重複項目移除查詢的相關注意事項:
- 保守的重複項目移除查詢策略是指定一份新資料表,也可以指定包含
WRITE_TRUNCATE
寫入配置的來源資料表。 - 重複項目移除查詢會將
row_number
資料欄 (包含1
這個值) 加到資料表結構定義尾端。這項查詢使用 GoogleSQL 的SELECT * EXCEPT
陳述式,從目的地資料表中排除row_number
資料欄。#standardSQL
前置字串會為此查詢啟用 GoogleSQL。此外,您也可以選取特定的資料欄名稱來略過此資料欄。 - 如要在移除重複項目後查詢即時資料,您也可以使用重複項目移除查詢來對資料表建立資料檢視。請注意,資料檢視的查詢成本是根據在資料檢視中選取的資料欄計算,這可能會導致位元組掃描大小過大。
以串流方式將資料傳入時間分區資料表
以串流方式將資料傳入時間分區資料表時,每個分區都會有一個串流緩衝區。如將 writeDisposition
屬性設為 WRITE_TRUNCATE
,當您在執行會覆寫分區的載入、查詢或複製工作時,系統會保留串流緩衝區。如要移除串流緩衝區,請對分區呼叫 tables.get
,確認串流緩衝區是空的。
擷取時間分區
將資料串流至擷取時間分區資料表時,BigQuery 會根據目前的 UTC 時間推斷目的地分區。
新抵達的資料位於串流緩衝區時,會暫時置於 __UNPARTITIONED__
分區。未分區資料累積到足夠的量以後,BigQuery 就會將資料分區到正確的分區。不過,資料移出 __UNPARTITIONED__
分區所需時間並無服務等級協議。查詢可以使用虛擬資料欄 (_PARTITIONTIME
或 _PARTITIONDATE
,視您偏好的資料類型而定) 從 __UNPARTITIONED__
分區篩選出 NULL
值,藉此從查詢中排除串流緩衝區的資料。
如果您要將資料串流至每日分區資料表,可以提供分區修飾符做為 insertAll
要求的一部分,藉此覆寫日期推斷結果。在 tableId
參數中加入修飾符。舉例來說,您可以使用分區修飾符,將資料串流至資料表 table1
中對應 2021-03-01 的分區:
table1$20210301
使用分區修飾符以串流方式傳輸資料時,可以根據目前的世界標準時間,以串流方式將資料傳輸至過去 31 天和未來 16 天之間 (相對於目前日期) 的分區。如要針對前述允許範圍外的日期寫入分區,請改用載入或查詢工作,如附加並覆寫分區資料表資料一文所述。
使用分區修飾符以串流方式傳送資料時,僅支援每日分區資料表。不支援每小時、每月或每年分區的資料表。
如要進行測試,可以使用 bq 指令列工具 bq insert
CLI 指令。例如,以下指令會將單一列以串流方式傳入 mydataset.mytable
分區資料表中日期為 2017 年 1 月 1 日 ($20170101
) 的分區:
echo '{"a":1, "b":2}' | bq insert 'mydataset.mytable$20170101'
依時間單位資料欄分區
您可以將資料串流至以 DATE
、DATETIME
或 TIMESTAMP
資料欄分區的資料表,但這些資料欄的值必須介於過去 10 年和未來 1 年之間。超出這個範圍的資料會遭到拒絕。
資料進行串流時,一開始會放在 __UNPARTITIONED__
分區中。未分區資料累積到足夠的量以後,BigQuery 就會自動重新分區資料,將資料放入適當的分區。不過,資料移出 __UNPARTITIONED__
分區所需時間並無服務水準協議。
- 注意:每日分割區的處理方式與每小時、每月和每年分割區不同。只有超出日期範圍 (過去 7 天至未來 3 天) 的資料會擷取至 UNPARTITIONED 分區,等待重新分區。另一方面,如果是以小時為單位的分區資料表,資料一律會擷取至 UNPARTITIONED 分區,之後再重新分區。
使用範本資料表自動建立資料表
範本資料表提供一種機制,可將邏輯資料表分成許多較小的資料表,以便建立較小的資料集 (例如,透過使用者 ID)。範本表格有下列限制。建議改用分區資料表和叢集資料表來達成此行為。
如要透過 BigQuery API 使用範本資料表,請將 templateSuffix
參數新增到 insertAll
要求。如果是 bq 指令列工具,請在 insert
指令中加入 template_suffix
旗標。假如 BigQuery 偵測到 templateSuffix
參數或 template_suffix
標記,就會將指定資料表視為基礎範本。並建立一份結構定義與指定資料表相同的新資料表,而且該資料表具有包含指定後置字元的名稱:
<targeted_table_name> + <templateSuffix>
只要使用範本資料表,您就可以省去個別建立資料表以及為每個資料表指定結構定義的負擔。您只需要建立一個範本,並提供不同的後置字元,BigQuery 就能為您建立新資料表。BigQuery 會將資料表放在同一個專案和資料集中。
使用範本資料表建立的資料表通常會在幾秒內提供。 在極少數情況下,可能需要較長時間才能使用。
變更範本資料表結構定義
如果您變更範本資料表結構定義,後續產生的所有資料表都會使用更新後的結構定義。先前產生的資料表不會受到影響,除非現有資料表仍有串流緩衝區。
就仍有串流緩衝區的現有資料表而言,假如您以回溯相容的方式修改範本資料表結構定義,主動串流產生的資料表結構定義也會隨之更新。不過,如果您以非回溯相容的方式修改範本資料表結構定義,使用舊結構定義的所有緩衝資料都將會遺失。此外,如果已產生的現有資料表使用現已不相容的舊結構定義,您就無法將新資料串流傳入表內。
變更範本資料表結構定義後,請等待變更傳播完畢,再嘗試插入新資料或查詢產生的資料表。插入新欄位的要求應該會在幾分鐘內成功,而查詢新欄位的嘗試可能需要最多 90 分鐘。
如要變更已產生資料表的結構定義,請等到透過範本資料表進行的串流作業停止,且已產生資料表的串流統計資料區塊已不存在 tables.get()
回應中 (表示資料表已沒有緩衝資料),否則請勿變更結構定義。
分區資料表和叢集資料表不會受到上述限制,因此建議使用這兩種機制。
範本資料表詳細資料
- 範本後置值
templateSuffix
(或--template_suffix
) 值只能包含英文字母 (a-z、A-Z)、數字 (0-9) 或底線 (_)。資料表名稱和資料表尾碼的總長度上限為 1024 個字元。- 配額
範本資料表受串流配額限制。專案每秒最多可使用範本表格建立 10 個表格,與
tables.insert
API 類似。這項配額僅適用於正在建立的資料表,不適用於正在修改的資料表。如果應用程式每秒需要建立超過 10 個資料表,建議使用叢集資料表。 舉例來說,您可以將高基數資料表 ID 放入單一叢集資料表的鍵欄。
- 存留時間 (TTL)
已產生的資料表會沿用資料集的到期時間。已產生的資料表跟一般的串流資料一樣,無法立即複製。
- 刪除重複資料
系統只會針對目的地資料表的相同參照內容刪除重複資料。 舉例來說,如果您同時使用範本資料表和一般
insertAll
指令,將資料串流至產生的資料表,範本資料表和一般insertAll
指令插入的資料列之間不會重複資料刪除。- 瀏覽次數
範本資料表和產生的資料表不得設為檢視畫面。
排解串流資料插入的問題
接下來的幾個小節將討論,如何排解您使用舊版 Streaming API 將資料串流到 BigQuery 中時所發生的錯誤。如要進一步瞭解如何解決串流資料插入的配額錯誤,請參閱「串流資料插入配額錯誤」。
失敗的 HTTP 回應代碼
如果您收到失敗的 HTTP 回應碼 (例如網路錯誤),就無法判斷串流插入作業是否成功。如果您嘗試重新傳送要求,可能會導致資料表中出現重複的資料列。為防止資料表出現重複的內容,請在傳送要求時設定 insertId
屬性。BigQuery 會利用 insertId
屬性來清除重複的內容。
如果您收到權限錯誤、資料表名稱無效的錯誤,或是超過配額的錯誤,代表系統沒有插入任何資料列,且整個要求都執行失敗。
成功的 HTTP 回應代碼
即使您收到
成功的 HTTP 回應代碼,您還是需要檢查回應的 insertErrors
屬性,判斷資料列的插入作業是否已執行成功,因為 BigQuery 有可能只成功插入了部分資料列。您可能會遇到下列其中一種情況:
- 所有資料列都已成功插入。如果
insertErrors
屬性是空白清單,代表所有資料列都已成功插入。 - 已成功插入部分資料列。除了發生有任何資料列中結構定義不相符的情況之外,在
insertErrors
屬性中列出的資料列都沒有插入資料表,而所有其他的資料列都已成功插入。errors
屬性會針對每個插入失敗的資料列,提供失敗的詳細原因。index
屬性會針對發生該錯誤的要求,提供從 0 開始的資料列索引。 - 未成功插入任何資料列。如果 BigQuery 在處理要求中個別的資料列時碰到結構定義不相符的情況,就不會插入任何資料列,並針對每個資料列傳回
insertErrors
項目,即使結構定義沒有不相符的資料列也算在內。沒有結構定義不相符的資料列會有reason
屬性設定為stopped
的錯誤,且可讓您照原樣重新傳送。而失敗的資料列會包含關於結構定義不相符的詳細資訊。如要瞭解各個 BigQuery 資料類型支援的通訊協定緩衝區類型,請參閱「資料類型轉換」。
串流資料插入的中繼資料錯誤
由於 BigQuery 的串流 API 是針對高插入率所設計,因此對基礎資料表中繼資料所做的修改最終會在與串流系統互動時保持一致。在大多數情況下,中繼資料變更會在幾分鐘內生效,但 API 回應在這段期間可能會反映出不一致的資料表狀態。
部分情況包括:
- 結構定義變更。如果您為最近受到串流資料插入的資料表修改結構定義,可能會收到指出結構定義不相符錯誤的回應,這是因為串流系統可能無法立刻反映出結構定義的變更。
- 資料表建立/刪除。串流至不存在的資料表會傳回
notFound
回應的變化類型。而後續的串流資料插入作業,可能無法立刻辨識出在回應中建立資料表的動作。同樣地,刪除或重新建立資料表時,串流資料插入可能會在一段時間內傳送至舊資料表。新資料表可能不會包含串流插入內容。 - 表格截斷。截斷資料表的資料 (例如查詢工作會使用 WRITE_TRUNCATE 的 writeDisposition 時),可能會導致後續插入的一致性出現落差。
遺失/無法取得資料
串流插入作業會暫時存放在寫入最佳化儲存空間,這類儲存空間的可用性特徵與代管儲存空間不同。BigQuery 中的某些作業不會與寫入最佳化儲存空間互動,例如資料表複製作業和 tabledata.list
等 API 方法。近期的串流資料不會出現在目的地資料表或輸出內容中。