העברת נתונים בסטרימינג באמצעות Storage Write API (gRPC)
באמצעות BigQuery Storage Write API (gRPC) אפשר להעביר נתונים בסטרימינג באופן רציף לטבלאות ב-BigQuery, כך שהרשומות יהיו זמינות לשאילתות עם זמן אחזור מינימלי. בהתאם לדרישות של עומס העבודה, אתם יכולים להשתמש בסטרימינג שמוגדר כברירת מחדל לכתיבה של לפחות פעם אחת, או ליצור סטרימינג מסוג committed עם היסטים של סטרימינג למסירה של פעם אחת בדיוק.
שימוש בסטרימינג שמוגדר כברירת מחדל לסמנטיקה של "לפחות פעם אחת"
אם האפליקציה שלכם יכולה לקבל את האפשרות שרשומות כפולות יופיעו בטבלת היעד, מומלץ להשתמש בסטרימינג שמוגדר כברירת מחדל בתרחישים של סטרימינג. בזרם ברירת המחדל נעשה שימוש בסוג committed, כך שהרשומות זמינות לשאילתות ברגע שהשרת מאשר את בקשת הכתיבה, בלי מסירה של פעם אחת בדיוק.
הקוד הבא מראה איך לכתוב נתונים לסטרים שמוגדר כברירת מחדל:
Java
במאמר ספריות הלקוח של BigQuery מוסבר איך להתקין את ספריית הלקוח ולהשתמש בה ב-BigQuery. למידע נוסף, קראו את מאמרי העזרה של BigQuery Java API.
כדי לבצע אימות ב-BigQuery, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.
Node.js
במאמר ספריות הלקוח של BigQuery מוסבר איך להתקין את ספריית הלקוח ולהשתמש בה ב-BigQuery.
כדי לבצע אימות ב-BigQuery, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.
Python
בדוגמה הבאה מוסבר איך להוסיף רשומה עם שני שדות באמצעות ה-stream שמוגדר כברירת מחדל:
from google.cloud import bigquery_storage_v1
from google.cloud.bigquery_storage_v1 import types
from google.cloud.bigquery_storage_v1 import writer
from google.protobuf import descriptor_pb2
import logging
import json
import sample_data_pb2
# The list of columns from the table's schema to search in the given data to write to BigQuery.
TABLE_COLUMNS_TO_CHECK = [
"name",
"age"
]
# Function to create a batch of row data to be serialized.
def create_row_data(data):
row = sample_data_pb2.SampleData()
for field in TABLE_COLUMNS_TO_CHECK:
# Optional fields will be passed as null if not provided
if field in data:
setattr(row, field, data[field])
return row.SerializeToString()
class BigQueryStorageWriteAppend(object):
# The stream name is: projects/{project}/datasets/{dataset}/tables/{table}/_default
def append_rows_proto2(
project_id: str, dataset_id: str, table_id: str, data: dict
):
write_client = bigquery_storage_v1.BigQueryWriteClient()
parent = write_client.table_path(project_id, dataset_id, table_id)
stream_name = f'{parent}/_default'
write_stream = types.WriteStream()
# Create a template with fields needed for the first request.
request_template = types.AppendRowsRequest()
# The request must contain the stream name.
request_template.write_stream = stream_name
# Generating the protocol buffer representation of the message descriptor.
proto_schema = types.ProtoSchema()
proto_descriptor = descriptor_pb2.DescriptorProto()
sample_data_pb2.SampleData.DESCRIPTOR.CopyToProto(proto_descriptor)
proto_schema.proto_descriptor = proto_descriptor
proto_data = types.AppendRowsRequest.ProtoData()
proto_data.writer_schema = proto_schema
request_template.proto_rows = proto_data
# Construct an AppendRowsStream to send an arbitrary number of requests to a stream.
append_rows_stream = writer.AppendRowsStream(write_client, request_template)
# Append proto2 serialized bytes to the serialized_rows repeated field using create_row_data.
proto_rows = types.ProtoRows()
for row in data:
proto_rows.serialized_rows.append(create_row_data(row))
# Appends data to the given stream.
request = types.AppendRowsRequest()
proto_data = types.AppendRowsRequest.ProtoData()
proto_data.rows = proto_rows
request.proto_rows = proto_data
append_rows_stream.send(request)
print(f"Rows to table: '{parent}' have been written.")
if __name__ == "__main__":
###### Uncomment the below block to provide additional logging capabilities ######
#logging.basicConfig(
# level=logging.DEBUG,
# format="%(asctime)s [%(levelname)s] %(message)s",
# handlers=[
# logging.StreamHandler()
# ]
#)
###### Uncomment the above block to provide additional logging capabilities ######
with open('entries.json', 'r') as json_file:
data = json.load(json_file)
# Change this to your specific BigQuery project, dataset, table details
BigQueryStorageWriteAppend.append_rows_proto2("PROJECT_ID","DATASET_ID", "TABLE_ID ",data=data)
דוגמת הקוד הזו תלויה במודול הפרוטוקול המקומפל sample_data_pb2.py. כדי ליצור את המודול המקומפל, מריצים את הפקודה protoc --python_out=. sample_data.proto, כאשר protoc הוא הקומפיילר של מאגר האחסון לפרוטוקולים. הקובץ sample_data.proto מגדיר את הפורמט של ההודעות שמשמשות בדוגמה של Python. כדי להתקין את המהדר של protoc, פועלים לפי ההוראות במאמר מאגרי אחסון לפרוטוקולים – פורמט חילופי הנתונים של Google.
הנה התוכן של הקובץ sample_data.proto:
message SampleData {
required string name = 1;
required int64 age = 2;
}
הסקריפט הזה צורך את הקובץ entries.json, שמכיל נתונים לדוגמה של שורות שצריך להוסיף לטבלה ב-BigQuery:
{"name": "Jim", "age": 35}
{"name": "Jane", "age": 27}
Rust
שימוש בריבוב (multiplexing)
אתם מפעילים ריבוב ברמת כותב הסטרימינג רק לסטרימינג שמוגדר כברירת מחדל. כדי להפעיל multiplexing ב-Java, צריך להפעיל את ה-method setEnableConnectionPool כשיוצרים אובייקט StreamWriter או JsonStreamWriter.
אחרי שמפעילים את מאגר החיבורים, ספריית הלקוח של Java מנהלת את החיבורים ברקע, ומגדילה את מספר החיבורים אם החיבורים הקיימים נחשבים לעמוסים מדי. כדי שההתאמה האוטומטית לעומס תהיה יעילה יותר, כדאי להקטין את המגבלה של maxInflightRequests.
// One possible way for constructing StreamWriter StreamWriter.newBuilder(streamName) .setWriterSchema(protoSchema) .setEnableConnectionPool(true) .setMaxInflightRequests(100) .build(); // One possible way for constructing JsonStreamWriter JsonStreamWriter.newBuilder(tableName, bigqueryClient) .setEnableConnectionPool(true) .setMaxInflightRequests(100) .build();
כדי להפעיל multiplexing ב-Go, קראו את המאמר שיתוף חיבורים (multiplexing).
כדי להפעיל multiplexing ב-Rust, צריך להפעיל את ה-method with_multiplexing(true) כשיוצרים כותב ברירת מחדל של זרם נתונים:
let writer = client .open_default_stream(table_name) .with_multiplexing(true) .build_arrow(schema) .await?;
שימוש בסוג מחויב לסמנטיקה של פעם אחת בדיוק
אם אתם צריכים סמנטיקה של כתיבה פעם אחת בדיוק, צרו זרם כתיבה מסוג committed. בסוג committed, הרשומות זמינות לשאילתה ברגע שהלקוח מקבל אישור מה-backend.
הסוג Committed מספק מסירה של פעם אחת בדיוק בתוך זרם, באמצעות שימוש בהיסטים של רשומות. באמצעות היסטים של רשומות, האפליקציה מציינת את ההיסט הבא של הוספה בכל קריאה ל-AppendRows. פעולת הכתיבה מתבצעת רק אם ערך ההיסט תואם להיסט של פעולת ה-append הבאה. מידע נוסף זמין במאמר ניהול היסטים של סטרימינג כדי להשיג סמנטיקה של פעם אחת בדיוק.
אם לא מציינים היסט, הרשומות מתווספות לסוף הנוכחי של הסטרימינג. במקרה כזה, אם בקשת הוספה מחזירה שגיאה, ניסיון חוזר עלול לגרום לכך שהרשומה תופיע יותר מפעם אחת בסטרימינג.
כדי להשתמש בסוג המחויב, מבצעים את השלבים הבאים:
Java
- מפעילים את
CreateWriteStreamכדי ליצור לפחות זרם אחד מסוג committed. - לכל סטרימינג, צריך להפעיל את
AppendRowsבלולאה כדי לכתוב קבוצות של רשומות. - קוראים ל-
FinalizeWriteStreamלכל שידור כדי לשחרר את השידור. אחרי שמפעילים את השיטה הזו, אי אפשר לכתוב יותר שורות לסטרים. השלב הזה הוא אופציונלי בסוג המחויב, אבל הוא עוזר למנוע חריגה מהמגבלה על מספר הסטרימינג הפעילים. מידע נוסף זמין במאמר הגבלת קצב היצירה של מקורות נתונים.
Node.js
- מפעילים את
createWriteStreamFullResponseכדי ליצור לפחות זרם אחד מסוג committed. - לכל סטרימינג, צריך להפעיל את
appendRowsבלולאה כדי לכתוב קבוצות של רשומות. - קוראים ל-
finalizeלכל שידור כדי לשחרר את השידור. אחרי שמפעילים את השיטה הזו, אי אפשר לכתוב יותר שורות לסטרימינג. השלב הזה הוא אופציונלי בסוג המחויב, אבל הוא עוזר למנוע חריגה מהמגבלה על מספר הסטרימינג הפעילים. מידע נוסף זמין במאמר הגבלת קצב היצירה של מקורות נתונים.
Rust
- מפעילים את
create_streamבלקוחWriteויוצריםCommittedWriterכדי ליצור זרם אחד או יותר בסוג committed. - לכל סטרימינג, צריך להפעיל את
appendבלולאה כדי לכתוב קבוצות של רשומות. - קוראים ל-
finalizeלכל שידור כדי לשחרר את השידור. אחרי שמפעילים את השיטה הזו, אי אפשר לכתוב שורות נוספות לסטרימינג. השלב הזה הוא אופציונלי בסוג המחויב, אבל הוא עוזר למנוע חריגה מהמגבלה על מספר הסטרימינג הפעילים. מידע נוסף זמין במאמר הגבלת קצב היצירה של מקורות נתונים.
אי אפשר למחוק מקור נתונים באופן מפורש. השידורים פועלים לפי אורך החיים (TTL) שמוגדר במערכת:
- לסטרימינג שהוגדר כ-committed יש TTL של שלושה ימים אם אין בו תנועה.
- כברירת מחדל, לשידור במאגר זמני יש TTL של שבעה ימים אם אין תנועה בשידור.
הקוד הבא מראה איך להשתמש בסוג המחויב:
Java
במאמר ספריות הלקוח של BigQuery מוסבר איך להתקין את ספריית הלקוח ולהשתמש בה ב-BigQuery. למידע נוסף, קראו את מאמרי העזרה של BigQuery Java API.
כדי לבצע אימות ב-BigQuery, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.
Node.js
במאמר ספריות הלקוח של BigQuery מוסבר איך להתקין את ספריית הלקוח ולהשתמש בה ב-BigQuery.
כדי לבצע אימות ב-BigQuery, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.
Rust
שימוש בפורמט Apache Arrow כדי להטמיע נתונים
הקוד הבא מראה איך להטמיע נתונים בפורמט Apache Arrow.
Python
בדוגמה הזו מוסבר איך להטמיע טבלת PyArrow שעברה סריאליזציה באמצעות הסטרימינג שמוגדר כברירת מחדל. דוגמה מפורטת יותר מקצה לקצה מופיעה בדוגמה של PyArrow ב-GitHub.
from google.cloud.bigquery_storage_v1 import types as gapic_types
from google.cloud.bigquery_storage_v1.writer import AppendRowsStream
from google.cloud import bigquery_storage_v1
def append_rows_with_pyarrow(
pyarrow_table: pyarrow.Table,
project_id: str,
dataset_id: str,
table_id: str,
):
bqstorage_write_client = bigquery_storage_v1.BigQueryWriteClient()
# Create request_template.
request_template = gapic_types.AppendRowsRequest()
request_template.write_stream = (
f"projects/{project_id}/datasets/{dataset_id}/tables/{table_id}/_default"
)
arrow_data = gapic_types.AppendRowsRequest.ArrowData()
arrow_data.writer_schema.serialized_schema = (
pyarrow_table.schema.serialize().to_pybytes()
)
request_template.arrow_rows = arrow_data
# Create AppendRowsStream.
append_rows_stream = AppendRowsStream(
bqstorage_write_client,
request_template,
)
# Create request with table data.
request = gapic_types.AppendRowsRequest()
request.arrow_rows.rows.serialized_record_batch = (
pyarrow_table.to_batches()[0].serialize().to_pybytes()
)
# Send request.
future = append_rows_stream.send(request)
# Wait for result.
future.result()
Java
במאמר ספריות הלקוח של BigQuery מוסבר איך להתקין את ספריית הלקוח ולהשתמש בה ב-BigQuery. למידע נוסף, קראו את מאמרי העזרה של BigQuery Java API.
כדי לבצע אימות ב-BigQuery, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.
Rust