批次要求
由於全球 HTTP 批次端點已淘汰,因此只針對 BigQuery API 的 HTTP 批次要求將在 2025 年 6 月 2 日停止運作。如果您的應用程式會傳送批次 HTTP 要求,請在 2025 年 6 月 2 日前將批次 HTTP 要求改為個別 HTTP 要求。
如要瞭解淘汰項目,請參閱下列常見問題。如要瞭解如何批次 HTTP 要求,請參閱批次要求相關文件。
BigQuery 批次 HTTP API 淘汰常見問題
為何淘汰 BigQuery 批次 HTTP 要求?
全球 HTTP 批次端點的支援功能是根據使用單一共用 Proxy 來接收所有 API 要求的架構而設計。由於 Google 已轉向採用更分散、高效能的架構,可將要求直接傳送至適當的 API 伺服器,因此我們不再支援這些全域端點。
下一個步驟是淘汰 BigQuery 批次 HTTP 要求。BigQuery 服務也會分散處理。高 QPS 方法由專屬後端處理。所有區域都會隔離,但 HTTP 批次要求可能會導致跨區域要求分散。這會導致批次處理效率不彰,並可能導致處理延遲時間增加,這與 HTTP 要求支援批次處理的初衷背道而行。
哪些內容已淘汰?
以下與 BigQuery API 互動的批次要求方法將不再運作:
- API 探索文件中指定的 REST API
batchPath
- Java 用戶端程式庫
BatchRequest
類別 - JavaScript 用戶端程式庫
Batch
物件 - C# 用戶端程式庫
BatchRequest
物件 - 其他用戶端程式庫:
BatchRequest
類別
如何遷移?
大多數 BigQuery 使用者不會使用批次 HTTP 要求。如果您仍在使用批次要求,請參考下列範例,將批次 HTTP 要求替換為個別 HTTP 要求。
REST
請按照 BigQuery API 參考資料章節的說明,傳送個別 HTTP 要求。請勿使用 /batch/v2/bigquery
路徑將要求合併成批次。
JavaScript
如果您使用的是 JavaScript,請先開始撰寫如下所示的程式碼區塊:
// Notice that the outer batch request contains inner API requests // for two different APIs. // Request to urlshortener API request1 = gapi.client.urlshortener.url.get({"shortUrl": "http://goo.gl/fbsS"}); // Request to zoo API request2 = gapi.client.zoo.animals.list(); // Request to urlshortener API request3 = gapi.client.urlshortener.url.get({"shortUrl": "https://goo.gl/XYFuPH"}); // Request to zoo API request4 = gapi.client.zoo.animal().get({"name": "giraffe"}); // Creating a batch request object batchRequest = gapi.client.newBatch(); // adding the 4 batch requests batchRequest.add(request1); batchRequest.add(request2); batchRequest.add(request3); batchRequest.add(request4); // print the batch request batchRequest.then(x=>console.log(x))
將上述程式碼區塊替換為如下程式碼區塊:
// Request to urlshortener API request1 = gapi.client.urlshortener.url.get({"shortUrl": "http://goo.gl/fbsS"}); // Request to zoo API request2 = gapi.client.zoo.animals.list(); // Request to urlshortener API request3 = gapi.client.urlshortener.url.get({"shortUrl": "http://goo.gl/fbsS"}) // Request to zoo API request4 = gapi.client.zoo.animals.list(); // print the 4 individual requests Promise.all([request1, request2, request3, request4]) .then(x=>console.log(x));
Python
如果您使用的是 Python,請先開始撰寫如下程式碼區塊:
from apiclient.http import BatchHttpRequest def insert_animal(request_id, response, exception): if exception is not None: # Do something with the exception pass else: # Do something with the response pass service = build('farm', 'v2') batch = service.new_batch_http_request(callback=insert_animal) batch.add(service.animals().insert(name="sheep")) batch.add(service.animals().insert(name="pig")) batch.add(service.animals().insert(name="llama")) batch.execute(http=http)
將上述程式碼區塊替換為如下程式碼區塊:
# import a new API to create a thread pool from concurrent.futures import ThreadPoolExecutor as PoolExecutor def run_it(request): print(request.execute()) service = build('farm', 'v2') request1 = service.animals().insert(name="sheep") request2 = service.animals().insert(name="pig") request3 = service.animals().insert(name="llama") with PoolExecutor(max_workers=4) as executor: for _ in executor.map(run_it,[request1, request2, request3]): pass
其他語言
與先前的範例相似,請將 BatchRequest
呼叫替換為個別要求。
取得遷移支援
如需遷移相關協助,請前往 Stack Overflow 發問。Google 工程師會監控及回答標有 google-bigquery 標記的問題。因此提出問題時,請使用這個標記。我們會盡快回答所有問題。
批次處理請求
本文說明如何批次處理 API 呼叫,以減少用戶端必須建立的 HTTP 連線數量。
本文專門說明如何透過傳送 HTTP 要求來提交批次要求。如果您是使用 Google 用戶端程式庫提交批次要求,請參閱用戶端程式庫的說明文件。
總覽
用戶端建立的每個 HTTP 連線都會造成一定程度的負擔。Google BigQuery API 支援批次作業,可以讓用戶端在單一 HTTP 要求中加入數個 API 呼叫。
以下是您可能想要使用批次作業的狀況範例:
- 您剛開始使用 API,有許多資料需要上傳。
- 使用者在您的應用程式離線 (中斷與網際網路的連線) 時變更了資料,所以應用程式必須傳送許多更新和刪除資料,讓本機資料能夠與伺服器同步處理。
在任一案例中,都不需要個別傳送每一個呼叫,只需將這些呼叫分組後組成單一 HTTP 要求。所有內部要求都必須前往相同的 Google API。
單一批次要求最多能包含 1,000 個呼叫,如果您必須進行更多呼叫,請使用多個批次要求。
注意:BigQuery API 批次系統使用的語法與 OData 批次處理系統相同,但語意不同。
批次詳細資料
批次要求是由多個 API 呼叫合併成一個 HTTP 要求,系統會將這個要求傳送至 API 探索文件中指定的 batchPath
。預設路徑為 /batch/api_name/api_version
。本節詳細說明批次語法,並在後半段提供範例。
注意:組成批次的 n 個要求在用量限制中會算成 n 個要求,而不是一個要求。批次要求會先分解成一組要求再進行處理。
批次要求的格式
批次要求是單一標準 HTTP 要求,內含多個使用 multipart/mixed
內容類型的 BigQuery API 呼叫。在主要 HTTP 要求中,每個分部都含有一個巢狀的 HTTP 要求。
每個部分都以專屬的 Content-Type: application/http
HTTP 標頭開頭。也可以有選用的 Content-ID
標頭。不過,部分標頭只是用來標示部分開頭,與巢狀要求分開。伺服器將批次要求展開為個別要求後,就會忽略部分標頭。
每個部分的主體都是完整的 HTTP 要求,各有專屬的動詞、網址、標頭和主體。HTTP 要求只能包含 URL 的路徑部分;批次要求禁止納入完整的 URL。
外部批次要求的 HTTP 標頭 (除了 Content-
標頭,例如 Content-Type
) 會套用至批次中的每個要求。如果您在外部要求和個別呼叫中均指定所提供的 HTTP 標頭,則個別呼叫標頭的值會覆寫外部批次要求標頭的值。個別呼叫的標頭只會套用於該呼叫。
例如,如果您提供 Authorization 標頭用於特定呼叫,則該標頭只會套用於該呼叫。如果您提供 Authorization 標頭用於外部要求,則除非個別呼叫以自己的 Authorization 標頭覆寫所提供的標頭,否則所提供的 Authorization 標頭會套用於所有個別呼叫。
當伺服器收到批次要求時,即會將外部要求的查詢參數和標頭 (在適用情況下) 套用至每一個分部,然後將每個分部視為不同的 HTTP 要求。
回應批次要求
伺服器的回應是單一標準 HTTP 回應,內含 multipart/mixed
內容類型;每個部分都是對批次要求中某個要求的回應,並按照要求的順序排列。
就像要求中的分部一樣,每個回應分部都含有完整的 HTTP 回應,包括狀態碼、標頭和內文;就像要求中的部分一樣,每個回應部分前面都會加上 Content-Type
標頭,標示部分的開頭。
如果要求的特定部分含有 Content-ID
標頭,則回應的對應部分就會含有相符的 Content-ID
標頭,原始值前方會加上字串 response-
,如以下範例所示。
注意:伺服器可能會以任意順序執行您的呼叫。不要期望呼叫會按您的指定順序執行。如果您想要確保兩個呼叫依指定順序執行,就不能以單一要求傳送它們,而要先傳送第一個呼叫,然後等到第一個呼叫的回應後才能傳送第二個呼叫。
範例
以下範例顯示批次作業的使用,其中示範用的一般 (虛構) API 稱為 Farm API。但同樣的概念也適用於 BigQuery API。
批次要求範例
POST /batch/farm/v1 HTTP/1.1 Authorization: Bearer your_auth_token Host: www.googleapis.com Content-Type: multipart/mixed; boundary=batch_foobarbaz Content-Length: total_content_length --batch_foobarbaz Content-Type: application/http Content-ID: <item1:12930812@barnyard.example.com> GET /farm/v1/animals/pony --batch_foobarbaz Content-Type: application/http Content-ID: <item2:12930812@barnyard.example.com> PUT /farm/v1/animals/sheep Content-Type: application/json Content-Length: part_content_length If-Match: "etag/sheep" { "animalName": "sheep", "animalAge": "5" "peltColor": "green", } --batch_foobarbaz Content-Type: application/http Content-ID: <item3:12930812@barnyard.example.com> GET /farm/v1/animals If-None-Match: "etag/animals" --batch_foobarbaz--
批次回應範例
這是前一節中範例要求的回應。
HTTP/1.1 200 Content-Length: response_total_content_length Content-Type: multipart/mixed; boundary=batch_foobarbaz --batch_foobarbaz Content-Type: application/http Content-ID: <response-item1:12930812@barnyard.example.com> HTTP/1.1 200 OK Content-Type application/json Content-Length: response_part_1_content_length ETag: "etag/pony" { "kind": "farm#animal", "etag": "etag/pony", "selfLink": "/farm/v1/animals/pony", "animalName": "pony", "animalAge": 34, "peltColor": "white" } --batch_foobarbaz Content-Type: application/http Content-ID: <response-item2:12930812@barnyard.example.com> HTTP/1.1 200 OK Content-Type: application/json Content-Length: response_part_2_content_length ETag: "etag/sheep" { "kind": "farm#animal", "etag": "etag/sheep", "selfLink": "/farm/v1/animals/sheep", "animalName": "sheep", "animalAge": 5, "peltColor": "green" } --batch_foobarbaz Content-Type: application/http Content-ID: <response-item3:12930812@barnyard.example.com> HTTP/1.1 304 Not Modified ETag: "etag/animals" --batch_foobarbaz--