將資料匯出為 Protobuf 欄
本文說明如何使用 BigQuery 使用者定義函式 (UDF),將 BigQuery 資料匯出為通訊協定緩衝區 (Protobuf) 資料欄。
使用 Protobuf 欄位的時機
BigQuery 提供多個內建函式,可格式化所選資料。其中一個做法是將多個資料欄值合併為單一 Protobuf 值,這麼做有以下優點:
- 物件類型安全。
- 與 JSON 相比,壓縮率更高、資料傳輸時間更短,且成本更低。
- 彈性:大多數程式設計語言都有程式庫可處理 Protobuf。
- 從多個資料欄讀取及建構單一物件時,負擔較小。
雖然其他欄類型也能提供型別安全,但使用 Protobuf 欄可提供完整型別的物件,減少應用程式層或管道其他部分需要完成的工作量。
不過,以 Protobuf 欄匯出 BigQuery 資料時,有以下限制:
- Protobuf 資料欄的索引或篩選效果不佳。依據 Protobuf 欄的內容搜尋可能較不準確。
- 以 Protobuf 格式排序資料可能很困難。
如果匯出工作流程受到這些限制,建議您考慮使用其他方法匯出 BigQuery 資料:
- 使用排程查詢搭配
EXPORT DATA
陳述式,即可依日期或時間排序匯出的 BigQuery 資料,並排定週期性匯出作業。BigQuery 支援將資料匯出為 Avro、CSV、JSON 和 Parquet 格式。 - 使用 Dataflow 以 Avro 或 CSV 檔案格式匯出 BigQuery 資料。
必要的角色
如要取得將 BigQuery 資料匯出為 Protobuf 欄所需的權限,請要求管理員為您授予專案的下列 IAM 角色:
-
建立使用者定義函式:
BigQuery 資料編輯者 (
roles/bigquery.dataEditor
) -
從 BigQuery 資料表匯出資料:
BigQuery 資料檢視者 (
roles/bigquery.dataViewer
) -
讀取及上傳檔案至 Cloud Storage:
Storage Object Creator (
roles/storage.objectCreator
)
如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和機構的存取權」。
建立 UDF
建立 UDF,將 BigQuery STRUCT
資料類型轉換為 Protobuf 欄:
在指令列中複製
bigquery-utils.git
存放區:git clone https://github.com/GoogleCloudPlatform/bigquery-utils.git
前往 Protobuf 匯出資料夾:
cd bigquery-utils/tools/protobuf_export
使用
cp
指令或作業系統的檔案瀏覽器,將 proto 檔案複製到./protos
子資料夾。「
./protos
」資料夾中已有一個名為「dummy.proto
」的範例 proto 檔案。從 GitHub 存放區安裝必要套件:
npm install
使用 webpack 組合套件:
npx webpack --config webpack.config.js --stats-error-details
在
./dist
子資料夾中找出pbwrapper.js
檔案,然後將檔案上傳至 Cloud Storage 值區。前往「BigQuery」頁面
使用查詢編輯器建立名為
toMyProtoMessage
的 UDF,從現有的 BigQuery 資料表資料欄建構 Protobuf 資料欄:CREATE FUNCTION DATASET_ID.toMyProtoMessage(input STRUCT<INPUT_FIELDS>) RETURNS BYTES LANGUAGE js OPTIONS ( library=["gs://BUCKET_NAME/pbwrapper.js"] ) AS r""" let message = pbwrapper.setup("PROTO_PACKAGE.PROTO_MESSAGE") return pbwrapper.parse(message, input) """;
更改下列內容:
DATASET_ID
:包含 UDF 的資料集 ID。INPUT_FIELDS
:用於 proto 檔案的 proto 訊息類型中的欄位,格式為field_name_1 field_type_1 [, field_name_2 field_type_2, ...]
。您必須將使用底線的任何訊息類型欄位,改為使用駝峰式大小寫。舉例來說,如果訊息類型如下所示,則輸入欄位值必須為
itemId int64, itemDescription string
:message ThisMessage { int64 item_id = 1; string item_description = 2; }
BUCKET_NAME
:包含pbwrapper.js
檔案的 Cloud Storage 值區名稱。PROTO_PACKAGE
:proto 檔案的套件。PROTO_MESSAGE
:proto 檔案的訊息類型。
舉例來說,如果您使用提供的
dummy.proto
檔案,CREATE FUNCTION
陳述式會如下所示:CREATE OR REPLACE FUNCTION mydataset.toMyProtoMessage(input STRUCT<dummyField STRING>) RETURNS BYTES LANGUAGE js OPTIONS ( library=["gs://mybucket/pbwrapper.js"] ) AS r""" let message = pbwrapper.setup("dummypackage.DummyMessage") return pbwrapper.parse(message, input) """;
將資料欄格式設為 Protobuf 值
執行 toMyProtoMessage
UDF,將 BigQuery 資料表欄格式化為 Protobuf 值:
SELECT
UDF_DATASET_ID.toMyProtoMessage(STRUCT(INPUT_COLUMNS)) AS protoResult
FROM
`PROJECT_ID.DATASET_ID.TABLE_NAME`
LIMIT
100;
更改下列內容:
UDF_DATASET_ID
:包含 UDF 的資料集 ID。INPUT_COLUMNS
:要格式化為 Protobuf 值的資料欄名稱,格式為column_name_1 [, column_name_2, ...]
。 資料欄可以是任何支援的純量值型別或非純量型別,包括ARRAY
和STRUCT
。輸入資料欄必須與 proto 訊息類型欄位的類型和數量相符。PROJECT_ID
:包含表格的專案 ID。如果資料集位於目前專案中,您可以略過識別專案的步驟。DATASET_ID
:包含資料表的資料集 ID。TABLE_NAME
:包含要格式化資料欄的資料表名稱。
舉例來說,如果您使用以 dummy.proto
為基礎的 toMyProtoMessage
UDF,下列 SELECT
陳述式會正常運作:
SELECT
mydataset.toMyProtoMessage(STRUCT(word)) AS protoResult
FROM
`bigquery-public-data.samples.shakespeare`
LIMIT 100;
使用 Protobuf 值
以 Protobuf 格式匯出 BigQuery 資料後,您現在可以將資料做為完全型別的物件或結構體使用。
以下程式碼範例提供多種處理或使用匯出資料的方式: