Introduzione all'API Storage Write (gRPC)

Puoi utilizzare l'API BigQuery Storage Write (gRPC) per trasmettere i flussi di dati in BigQuery. Questo documento descrive l'architettura, le funzionalità e i casi d'uso dell'API Storage Write (gRPC).

Per i nuovi progetti, consigliamo di utilizzare l'API Storage Write (gRPC) anziché l'API Storage Write (REST). L'API Storage Write (gRPC) offre prezzi inferiori e funzionalità più solide, tra cui la semantica di consegna "exactly-once".

Autorizzazioni obbligatorie

Per utilizzare l'API Storage Write (gRPC), devi disporre delle autorizzazioni bigquery.tables.updateData.

I seguenti ruoli IAM (Identity and Access Management) predefiniti includono le autorizzazioni bigquery.tables.updateData:

  • bigquery.dataEditor
  • bigquery.dataOwner
  • bigquery.admin

Per saperne di più sui ruoli e sulle autorizzazioni IAM in BigQuery, consulta Ruoli e autorizzazioni predefiniti.

Ambiti di autenticazione

L'utilizzo dell'API Storage Write (gRPC) richiede uno dei seguenti ambiti OAuth:

  • https://www.googleapis.com/auth/bigquery
  • https://www.googleapis.com/auth/cloud-platform
  • https://www.googleapis.com/auth/bigquery.insertdata

Per saperne di più, consulta Panoramica dell'autenticazione.

Panoramica dell'API Storage Write (gRPC)

L'astrazione principale nell'API Storage Write (gRPC) è uno stream. Un flusso scrive i dati in una tabella BigQuery. Più di uno stream può scrivere contemporaneamente nella stessa tabella.

Stream predefinito

L'API Storage di scrittura (gRPC) fornisce uno stream predefinito, progettato per scenari di streaming in cui i dati arrivano continuamente. Ha le seguenti caratteristiche:

  • I dati scritti nel flusso predefinito sono immediatamente disponibili per le query.
  • Lo stream predefinito supporta la semantica at-least-once.
  • Non è necessario creare esplicitamente lo stream predefinito.

Se esegui la migrazione dall'API Storage Write (REST), valuta la possibilità di utilizzare lo stream predefinito. Ha una semantica di scrittura simile, con una maggiore resilienza dei dati e meno limitazioni di scalabilità.

Flusso API:

  1. AppendRows (loop)

Per ulteriori informazioni e un esempio di codice, consulta Utilizzare lo stream predefinito per la semantica at-least-once.

Stream creati dalle applicazioni

Puoi creare esplicitamente uno stream se hai bisogno di uno dei seguenti comportamenti:

  • Semantica di scrittura esattamente una volta tramite l'utilizzo di offset di stream.
  • Supporto per ulteriori proprietà ACID.

In generale, i flussi creati dalle applicazioni offrono un maggiore controllo sulle funzionalità a costo di una maggiore complessità.

Quando crei uno stream, specifichi un tipo. Il tipo controlla quando i dati scritti nello stream diventano visibili in BigQuery per la lettura.

Tipo in attesa

Nel tipo in attesa, i record vengono memorizzati nel buffer in uno stato in attesa finché non commit lo stream. Quando esegui il commit di uno stream, tutti i dati in attesa diventano disponibili per la lettura. Il commit è un'operazione atomica. Utilizza questo tipo per i workload batch, in alternativa ai job di caricamento BigQuery. Per maggiori informazioni, consulta Caricare i dati in batch utilizzando l'API Storage Write (gRPC).

Flusso API:

  1. CreateWriteStream
  2. AppendRows (loop)
  3. FinalizeWriteStream
  4. BatchCommitWriteStreams

Tipo di impegno

Nel tipo di commit, i record sono disponibili per la lettura immediatamente dopo la scrittura nel flusso. Utilizza questo tipo per i workload di streaming che richiedono una latenza di lettura minima. Lo stream predefinito utilizza un tipo di commit almeno una volta. Per saperne di più, consulta Utilizzare il tipo di commit per la semantica exactly-once.

Flusso API:

  1. CreateWriteStream
  2. AppendRows (loop)
  3. FinalizeWriteStream (facoltativo)

Tipo memorizzato nel buffer

Il tipo bufferizzato è un tipo avanzato che in genere non deve essere utilizzato, tranne con il connettore BigQuery I/O di Apache Beam. Se hai piccoli batch che vuoi garantire che vengano visualizzati insieme, utilizza il tipo di commit e invia ogni batch in una richiesta. In questo tipo, vengono forniti commit a livello di riga e i record vengono memorizzati nel buffer finché le righe non vengono eseguite scaricando lo stream.

Flusso API:

  1. CreateWriteStream
  2. AppendRowsFlushRows (loop)
  3. FinalizeWriteStream (facoltativo)

Selezionare un tipo

Utilizza il seguente diagramma di flusso per decidere il tipo più adatto al tuo carico di lavoro:

immagine

Dettagli API

Tieni presente quanto segue quando utilizzi l'API Storage Write:

AppendRows

Il metodo AppendRows aggiunge uno o più record al flusso. La prima chiamata a AppendRows deve contenere un nome di stream insieme allo schema dei dati, specificato come DescriptorProto. In alternativa, puoi aggiungere uno schema Arrow serializzato nella prima chiamata a AppendRows se importi dati nel formato Apache Arrow. Come best practice, invia un batch di righe in ogni chiamata AppendRows. Non inviare una riga alla volta.

Gestione del buffer di protocollo

I buffer di protocollo forniscono un meccanismo estensibile, indipendente dal linguaggio e dalla piattaforma per serializzare i dati strutturati in modo compatibile con le versioni precedenti e successive. Sono vantaggiosi in quanto forniscono un'archiviazione compatta dei dati con un'analisi rapida ed efficiente. Per scoprire di più sui buffer di protocollo, consulta la panoramica dei buffer di protocollo.

Se intendi utilizzare l'API direttamente con un messaggio buffer di protocollo predefinito, il messaggio buffer di protocollo non può utilizzare uno specificatore package e tutti i tipi di enumerazione o nidificati devono essere definiti all'interno del messaggio radice di primo livello. Non sono consentiti riferimenti a messaggi esterni. Per un esempio, vedi sample_data.proto.

I client Java e Go supportano buffer di protocollo arbitrari, perché la libreria client normalizza lo schema del buffer di protocollo.

Gestione di Apache Arrow

Apache Arrow è un formato colonnare universale e una cassetta degli attrezzi multilingue per l'elaborazione dei dati. Apache Arrow fornisce un formato di memoria indipendente dalla lingua e orientato alle colonne per dati piatti e gerarchici, organizzati per operazioni analitiche efficienti su hardware moderno. L'API Storage Write (gRPC) supporta l'importazione di Arrow utilizzando lo schema e i dati Arrow serializzati nella classe AppendRowsRequest. Le librerie client Python e Java includono il supporto integrato per l'importazione di Apache Arrow.

FinalizeWriteStream

Il metodo FinalizeWriteStream finalizza lo stream in modo che non sia possibile aggiungere nuovi dati. Questo metodo è obbligatorio per il tipo Pending e facoltativo per i tipi Committed e Buffered. Il flusso predefinito non supporta questo metodo.

Gestione degli errori

Se si verifica un errore, l'oggetto google.rpc.Status restituito può includere un StorageError nei dettagli dell'errore. Consulta StorageErrorCode per trovare il tipo di errore specifico. Per maggiori informazioni sul modello di errore dell'API Google, consulta Errori.

Connessioni

L'API Storage Write (gRPC) è un'API gRPC che utilizza connessioni bidirezionali. Il metodo AppendRows crea una connessione a uno stream. Puoi aprire più connessioni sullo stream predefinito. Queste aggiunte sono asincrone, il che ti consente di inviare una serie di scritture contemporaneamente. I messaggi di risposta su ogni connessione bidirezionale arrivano nello stesso ordine in cui sono state inviate le richieste.

Gli stream creati dall'applicazione possono avere una sola connessione attiva. Come best practice, limita il numero di connessioni attive e utilizza una connessione per il maggior numero possibile di scritture di dati. Quando utilizzi lo stream predefinito in Java o Go, puoi utilizzare il multiplexing dell'API Storage Write (gRPC) per scrivere in più tabelle di destinazione con connessioni condivise.

In genere, una singola connessione supporta almeno 1 MBps di throughput. Il limite superiore dipende da diversi fattori, come la larghezza di banda della rete, lo schema dei dati e il carico del server. Quando una connessione raggiunge il limite di velocità effettiva, le richieste in entrata potrebbero essere rifiutate o messe in coda finché il numero di richieste in corso non diminuisce. Se hai bisogno di una maggiore velocità effettiva, crea più connessioni.

BigQuery chiude la connessione gRPC se rimane inattiva per troppo tempo. In questo caso, il codice di risposta è HTTP 409. La connessione gRPC può essere chiusa anche in caso di riavvio del server o per altri motivi. Se si verifica un errore di connessione, crea una nuova connessione. Le librerie client Java e Go si riconnettono automaticamente se la connessione viene chiusa.

Supporto della libreria client

Le librerie client per l'API Storage Write (gRPC) esistono in più linguaggi di programmazione ed espongono i costrutti API basati su gRPC sottostanti. Questa API sfrutta funzionalità avanzate come lo streaming bidirezionale, che potrebbe richiedere un lavoro di sviluppo aggiuntivo per il supporto. A questo scopo, per questa API sono disponibili diverse astrazioni di livello superiore che semplificano queste interazioni e riducono i problemi degli sviluppatori. Ti consigliamo di utilizzare queste altre astrazioni della libreria, se possibile.

Questa sezione fornisce ulteriori dettagli su lingue e librerie in cui sono state fornite agli sviluppatori funzionalità aggiuntive oltre all'API generata.

Per visualizzare esempi di codice relativi all'API Storage Write (gRPC), consulta Tutti gli esempi di codice BigQuery.

Client Java

La libreria client Java fornisce due oggetti writer:

  • StreamWriter: accetta i dati in formato buffer di protocollo.

  • JsonStreamWriter: accetta i dati in formato JSON e li converte in buffer del protocollo prima di inviarli via cavo. JsonStreamWriter supporta anche gli aggiornamenti automatici dello schema. Se lo schema della tabella cambia, lo scrittore si riconnette automaticamente al nuovo schema, consentendo al client di inviare dati utilizzando il nuovo schema.

Il modello di programmazione è simile per entrambi gli autori. La differenza principale è il modo in cui formatti il payload.

L'oggetto writer gestisce una connessione all'API Storage Write (gRPC). L'oggetto writer pulisce automaticamente le richieste, aggiunge le intestazioni di routing regionale alle richieste e si riconnette dopo gli errori di connessione. Se utilizzi direttamente l'API gRPC, devi gestire questi dettagli.

Puoi anche utilizzare il formato di importazione Apache Arrow come protocollo alternativo per importare i dati utilizzando l'API Storage Write (gRPC). Per saperne di più, consulta Utilizzare il formato Apache Arrow per importare i dati.

Client Go

Il client Go utilizza un'architettura client-server per codificare i messaggi in formato buffer di protocollo utilizzando proto2. Per informazioni dettagliate su come utilizzare il client Go, con esempi di codice, consulta la documentazione di Go.

Client Python

Il client Python è un client di livello inferiore che esegue il wrapping dell'API gRPC. Per utilizzare questo client, devi inviare i dati come protocol buffer, seguendo il flusso dell'API per il tipo specificato.

Evita di utilizzare la generazione dinamica di messaggi proto in Python, poiché le prestazioni di questa libreria sono inferiori agli standard.

Per scoprire di più sull'utilizzo dei buffer di protocollo con Python, leggi il tutorial Nozioni di base sui buffer di protocollo in Python.

Puoi anche utilizzare il formato di importazione Apache Arrow come protocollo alternativo per importare i dati utilizzando l'API Storage Write. Per maggiori informazioni, consulta Utilizzare il formato Apache Arrow per importare i dati.

Client NodeJS

La libreria client NodeJS accetta input JSON e fornisce il supporto per la riconnessione automatica. Per informazioni dettagliate sull'utilizzo del client, consulta la documentazione.

Handle non disponibile

I nuovi tentativi con backoff esponenziale possono ridurre gli errori casuali e i brevi periodi di mancata disponibilità del servizio, ma per evitare l'eliminazione di righe durante periodi prolungati di mancata disponibilità è necessario un approccio più ponderato. In particolare, se un client non riesce a inserire una riga, cosa deve fare?

La risposta dipende dai tuoi requisiti. Ad esempio, se BigQuery viene utilizzato per l'analisi operativa in cui alcune righe mancanti sono accettabili, il client può rinunciare dopo alcuni tentativi e scartare i dati. Se, invece, ogni riga è fondamentale per l'attività, ad esempio con i dati finanziari, devi avere una strategia per conservare i dati fino a quando non possono essere inseriti in un secondo momento.

Un modo comune per gestire gli errori persistenti è pubblicare le righe in un argomento Pub/Sub per la valutazione e l'eventuale inserimento successivi. Un altro metodo comune è quello di rendere persistenti temporaneamente i dati sul client. Entrambi i metodi possono mantenere i client sbloccati, garantendo al contempo che tutte le righe possano essere inserite una volta ripristinata la disponibilità.

Esegui lo streaming nelle tabelle partizionate

L'API Storage Write (gRPC) supporta lo streaming dei dati nelle tabelle partizionate.

Quando i dati vengono trasmessi in streaming, vengono inizialmente inseriti nella partizione __UNPARTITIONED__. Una volta raccolti dati non partizionati sufficienti, BigQuery ripartiziona i dati, inserendoli nella partizione appropriata. Tuttavia, non esiste un accordo sul livello del servizio (SLA) che definisca il tempo necessario per spostare i dati dalla partizione __UNPARTITIONED__.

Per le tabelle partizionate in base all'ora di importazione e partizionate in base alla colonna dell'unità di tempo, i dati non partizionati possono essere esclusi da una query filtrando i valori NULL dalla partizione __UNPARTITIONED__ utilizzando una delle pseudocolonne (_PARTITIONTIME o _PARTITIONDATE a seconda del tipo di dati preferito).

Partizionamento per tempo di importazione

Quando esegui lo streaming in una tabella partizionata per data di acquisizione, l'API Storage Write (gRPC) deduce la partizione di destinazione dall' ora UTC corrente del sistema.

Se trasmetti dati in streaming in una tabella partizionata giornalmente, puoi eseguire l'override dell'inferenza della data fornendo un decoratore di partizione come parte della richiesta. Includi il decoratore nel parametro tableID. Ad esempio, puoi trasmettere in streaming alla partizione corrispondente al giorno 01/06/2025 per la tabella table1 utilizzando il decoratore di partizione table1$20250601.

Quando esegui lo streaming con un decoratore di partizioni, puoi eseguire lo streaming nelle partizioni da 31 giorni nel passato a 16 giorni nel futuro. Per scrivere nelle partizioni per le date al di fuori di questi limiti, utilizza un job di caricamento o query, come descritto in Scrivere dati in una partizione specifica.

Lo streaming che utilizza un decoratore di partizione è supportato solo per le tabelle partizionate giornalmente, non per quelle partizionate orariamente, mensilmente o annualmente.

Partizionamento per colonne di unità di tempo

Quando esegui lo streaming in una tabella partizionata per unità di tempo, BigQuery inserisce automaticamente i dati nella partizione corretta in base ai valori della colonna di partizionamento DATE, DATETIME o TIMESTAMP predefinita della tabella. Puoi trasmettere dati in streaming in una tabella partizionata per colonna di unità di tempo se i dati a cui fa riferimento la colonna di partizionamento si trovano tra 10 anni nel passato e 1 anno nel futuro.

Partizionamento per intervalli di numeri interi

Quando esegui lo streaming in una tabella partizionata per intervallo di numeri interi, BigQuery inserisce automaticamente i dati nella partizione corretta in base ai valori della colonna di partizionamento INTEGER predefinita della tabella.

Plug-in di output dell'API Storage Write (gRPC) di Fluent Bit

Il plug-in di output dell'API Storage Write (gRPC) di Fluent Bit automatizza il processo di importazione dei record JSON in BigQuery, eliminando la necessità di scrivere codice. Con questo plug-in, devi solo configurare un plug-in di input compatibile e impostare un file di configurazione per iniziare a trasmettere in streaming i dati. Fluent Bit è un processore e un forwarder di log open source e multipiattaforma che utilizza plug-in di input e output per gestire diversi tipi di origini e sink di dati.

Questo plug-in supporta quanto segue:

  • Semantica di tipo almeno una volta.
  • Semantica di esecuzione esatta una sola volta utilizzando il tipo di commit.
  • Scalabilità dinamica per i flussi predefiniti, quando viene indicata la contropressione.

Supporto di Apache Iceberg

Puoi utilizzare l'API Storage Write (gRPC) con Lakehouse for Apache Iceberg per trasmettere dati in streaming nelle tabelle Iceberg. Per ulteriori informazioni, consulta API BigQuery Storage Write (gRPC) nella documentazione di Lakehouse.

Metriche del progetto API Storage Write (gRPC)

Per le metriche per monitorare l'importazione dati con l'API Storage Write (gRPC), utilizza la visualizzazione INFORMATION_SCHEMA.WRITE_API_TIMELINE o consulta le metriche Google Cloud .

Utilizzare DML (Data Manipulation Language) con i dati di streaming recenti

Puoi utilizzare il Data Manipulation Language (DML), ad esempio le istruzioni UPDATE, DELETE o MERGE, per modificare le righe scritte di recente in una tabella BigQuery dall'API BigQuery Storage Write (gRPC). Le scritture recenti sono quelle che si sono verificate negli ultimi 30 minuti.

Per ulteriori informazioni sull'utilizzo di DML per modificare i dati in streaming, consulta Utilizzo di Data Manipulation Language.

Limitazioni

  • Il supporto per l'esecuzione di istruzioni DML mutanti sui dati di streaming recenti non si estende ai dati di streaming utilizzando l'API Storage Write (REST).
  • L'esecuzione di istruzioni DML mutanti all'interno di una transazione con più istruzioni sui dati di streaming recenti non è supportata.

Quote dell'API Storage Write (gRPC)

Per informazioni su quote e limiti dell'API Storage Write (gRPC), vedi Quote e limiti dell'API BigQuery Storage Write (gRPC).

Puoi monitorare l'utilizzo delle quote per le connessioni simultanee e il throughput nella pagina Quote della consoleGoogle Cloud .

Calcolare il throughput

Supponiamo che il tuo obiettivo sia raccogliere log da 100 milioni di endpoint creando 1500 record di log al minuto. A questo punto, puoi stimare il throughput come 100 million * 1,500 / 60 seconds = 2.5 GB per second. Devi assicurarti in anticipo di avere una quota adeguata per gestire questo throughput.

Prezzi dell'API Storage Write (gRPC)

Per i prezzi, consulta Prezzi dell'acquisizione dei dati.

Caso d'uso di esempio

Supponiamo che esista una pipeline che elabora i dati sugli eventi dai log degli endpoint. Gli eventi vengono generati continuamente e devono essere disponibili per le query in BigQuery il prima possibile. Poiché l'aggiornamento dei dati è fondamentale per questo caso d'uso, l'API Storage Write (gRPC) è la scelta migliore per importare i dati in BigQuery. Un'architettura consigliata per mantenere questi endpoint snelli consiste nell'inviare eventi a Pub/Sub, da dove vengono utilizzati da una pipeline Dataflow in modalità flusso che trasmette direttamente a BigQuery.

Un problema di affidabilità principale per questa architettura è come gestire l'errore di inserimento di un record in BigQuery. Se ogni record è importante e non può essere perso, i dati devono essere memorizzati nel buffer prima di tentare l'inserimento. Nell'architettura consigliata sopra, Pub/Sub può svolgere il ruolo di buffer con le sue funzionalità di conservazione dei messaggi. La pipeline Dataflow deve essere configurata per riprovare gli inserimenti di streaming BigQuery con backoff esponenziale troncato. Una volta esaurita la capacità di Pub/Sub come buffer, ad esempio in caso di mancata disponibilità prolungata di BigQuery o di un errore di rete, i dati devono essere resi persistenti sul client e il client ha bisogno di un meccanismo per riprendere l'inserimento dei record persistenti una volta ripristinata la disponibilità. Per saperne di più su come gestire questa situazione, leggi il post del blog Guida all'affidabilità di Google Pub/Sub.

Un altro caso di errore da gestire è quello di un record dannoso. Un record non valido è un record rifiutato da BigQuery perché l'inserimento non è riuscito a causa di un errore non riproducibile o un record che non è stato inserito correttamente dopo il numero massimo di tentativi. Entrambi i tipi di record devono essere memorizzati in una "coda di messaggi non recapitabili" dalla pipeline Dataflow per ulteriori indagini.

Se è richiesta la semantica exactly-once, crea un flusso di scrittura di tipo committed, con offset dei record forniti dal client. In questo modo si evitano duplicati, poiché l'operazione di scrittura viene eseguita solo se il valore di offset corrisponde all'offset di accodamento successivo. Se non viene fornito un offset, i record vengono aggiunti alla fine corrente dello stream e il tentativo di ripetizione di un'aggiunta non riuscita potrebbe comportare la visualizzazione del record più di una volta nello stream.

Se non sono richieste garanzie di esecuzione esatta, la scrittura nel flusso predefinito consente un throughput più elevato e non viene conteggiata ai fini del limite di quota per la creazione di flussi di scrittura.

Stima il throughput della tua rete e assicurati in anticipo di avere una quota adeguata per erogare il throughput.

Se il tuo carico di lavoro genera o elabora dati a una velocità molto irregolare, prova a smussare eventuali picchi di carico sul client e trasmetti in streaming in BigQuery con una velocità effettiva costante. In questo modo, la pianificazione della capacità può essere semplificata. Se non è possibile, assicurati di essere pronto a gestire gli errori 429 (risorsa esaurita) se e quando la velocità effettiva supera la quota durante i picchi brevi.

Per un esempio dettagliato di come utilizzare l'API Storage Write (gRPC), vedi Trasmettere dati in streaming utilizzando l'API Storage Write (gRPC).

Passaggi successivi