Introduzione all'API Storage Write (gRPC)

L'API BigQuery Storage Write (gRPC) consente di caricare record in modalità flusso e batch in BigQuery tramite connessioni gRPC bidirezionali.

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 di importazione inferiori e funzionalità più efficaci, tra cui transazioni a livello di stream e semantica di distribuzione "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 di base nell'API Storage Write (gRPC) è uno stream. Uno stream scrive i dati in una tabella BigQuery. Più stream possono scrivere contemporaneamente nella stessa tabella.

Stream predefinito

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

  • I dati scritti nello stream 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 dell'API:

  1. AppendRows (loop)

Per ulteriori informazioni e un esempio di codice, consulta Utilizza il flusso predefinito per la semantica di tipo at-least-once.

Stream creati dall'applicazione

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

  • Semantica di scrittura exactly-once tramite l'utilizzo di offset di stream.
  • Supporto di proprietà ACID aggiuntive.

In generale, i flussi creati dall'applicazione offrono un maggiore controllo sulla funzionalità, ma comportano 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 di stato In attesa

Nel tipo in attesa, i record vengono memorizzati nel buffer in uno stato in attesa finché non esegui il commit dello 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, come alternativa ai job di caricamento BigQuery. Per saperne di più, consulta Carica i dati in batch utilizzando l'API Storage Write (gRPC).

Flusso dell'API:

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

Tipo di impegno

Nel tipo committed, i record sono disponibili per la lettura immediatamente dopo la scrittura nello stream. Utilizza questo tipo per i workload di flussi di dati che richiedono una latenza di lettura minima. Lo stream predefinito utilizza una forma "at-least-once" del tipo committed. Per saperne di più, consulta Utilizza il tipo di commit per la semantica "exactly-once".

Flusso dell'API:

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

Tipo di buffer

Il tipo con buffer è un tipo avanzato che in genere non deve essere utilizzato, ad eccezione del connettore BigQuery I/O di Apache Beam. Se hai piccoli batch che vuoi che vengano visualizzati insieme, utilizza il tipo committed e invia ogni batch in un'unica richiesta. In questo tipo, vengono forniti commit a livello di riga e i record vengono memorizzati nel buffer fino a quando non viene eseguito il commit delle righe tramite lo svuotamento dello stream.

Flusso dell'API:

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

Selezione di un tipo

Utilizza il seguente diagramma di flusso per decidere quale tipo è più adatto al tuo workload:

immagine

Dettagli API

Quando utilizzi l'API Storage Write, tieni presente quanto segue:

AppendRows

Il metodo AppendRows aggiunge uno o più record allo stream. 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 i dati nel formato Apache Arrow. Come best practice, invia un batch di righe in ogni chiamata AppendRows. Non inviare una riga alla volta.

Gestione dei 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 successive e precedenti. Sono vantaggiosi in quanto forniscono un'archiviazione dei dati compatta con un'analisi rapida ed efficiente. Per scoprire di più sui buffer di protocollo, consulta la panoramica dei buffer di protocollo.

Se utilizzi l'API direttamente con un messaggio buffer di protocollo predefinito, il messaggio buffer di protocollo non può utilizzare un identificatore package e tutti i tipi nidificati o di enumerazione devono essere definiti all'interno del messaggio principale di primo livello. I riferimenti a messaggi esterni non sono consentiti. Per un esempio, consulta 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 un toolbox multilingue per il trattamento dati. Apache Arrow fornisce un formato di memoria orientato alle colonne e indipendente dal linguaggio per dati piatti e gerarchici, organizzati per operazioni di analisi 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, Java e Rust 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 nel tipo Pending e facoltativo nei tipi Committed e Buffered. Lo stream 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 la StorageErrorCode per trovare il tipo di errore specifico. Per saperne di più sul modello di errore dell'API di 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, Go o Rust, 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 una velocità effettiva di almeno 1 MBps. 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 throughput, le richieste in entrata potrebbero essere rifiutate o messe in coda finché il numero di richieste in corso non diminuisce. Se hai bisogno di un throughput maggiore, 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, Go e Rust si riconnettono automaticamente se la connessione viene chiusa.

Supporto delle librerie client

Le librerie client per l'API Storage Write (gRPC) esistono in più linguaggi di programmazione ed espongono i costrutti dell'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 le preoccupazioni degli sviluppatori. Ti consigliamo di utilizzare queste altre astrazioni della libreria, se possibile.

Questa sezione fornisce ulteriori dettagli sui linguaggi e sulle 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 di protocollo prima di inviarli tramite cavo. JsonStreamWriter supporta anche gli aggiornamenti automatici dello schema. Se lo schema della tabella cambia, il writer si riconnette automaticamente con il nuovo schema, consentendo al client di inviare dati utilizzando il nuovo schema.

Il modello di programmazione è simile per entrambi i writer. 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 Utilizza il formato Apache Arrow per importare i dati.

Client Go

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

Client Python

Il client Python è un client di livello inferiore che aggrega l'API gRPC. Per utilizzare questo client, devi inviare i dati come buffer di protocollo, 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 non sono ottimali.

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 saperne di più, consulta Utilizza il formato Apache Arrow per importare i dati.

Client NodeJS

La libreria client NodeJS accetta l'input JSON e fornisce il supporto per la riconnessione automatica. Consulta la documentazione per i dettagli su come utilizzare il client.

Client Rust

La libreria client Rust fornisce un client Write e oggetti writer tipizzati per ogni tipo di stream (DefaultWriter, CommittedWriter, PendingWriter e BufferedWriter). I writer accettano i dati nel formato Apache Arrow e gestiscono automaticamente le connessioni, le intestazioni di routing, i tentativi e le riconnessioni dell'API Storage Write (gRPC) dopo gli errori di connessione. Per importare i dati JSON, puoi convertire i record JSON in batch di record Apache Arrow utilizzando il crate arrow-json.

Consulta la documentazione di Rust per informazioni dettagliate su come utilizzare il client Rust e consulta Utilizza il formato Apache Arrow per importare i dati per un esempio di codice.

Gestisci la non disponibilità

La ripetizione dei tentativi con backoff esponenziale può mitigare gli errori casuali e i brevi periodi di indisponibilità del servizio, ma per evitare di perdere righe durante un'indisponibilità prolungata è necessaria una maggiore attenzione. In particolare, se un client non riesce ripetutamente 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 sono accettabili alcune righe mancanti, il client può rinunciare dopo alcuni tentativi e ignorare i dati. Se, invece, ogni riga è fondamentale per l'attività, come nel caso dei dati finanziari, devi avere una strategia per rendere persistenti i dati finché 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 una valutazione successiva e un eventuale inserimento. Un altro metodo comune è quello di conservare temporaneamente i dati sul client. Entrambi i metodi possono mantenere i client sbloccati e, al contempo, garantire che tutte le righe possano essere inserite una volta ripristinata la disponibilità.

Flusso in tabelle partizionate

L'API Storage Write (gRPC) supporta i flussi di dati nelle tabelle partizionate.

Quando i dati vengono trasmessi in streaming, vengono inizialmente inseriti nella partizione __UNPARTITIONED__. Dopo aver raccolto un numero sufficiente di dati non partizionati, BigQuery li ripartiziona inserendoli nella partizione appropriata. Tuttavia, non esiste un accordo sul livello del servizio (SLA) che definisca il tempo necessario per lo spostamento dei dati dalla partizione __UNPARTITIONED__.

Per le tabelle partizionate in base al momento dell'importazione e partizionate in base alla colonna di 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 data 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 di sistema corrente.

Se stai trasmettendo dati 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 01/06/2025 per la tabella table1 utilizzando il decoratore di partizione table1$20250601.

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

Lo streaming con un decoratore di partizione è supportato solo per le tabelle partizionate giornalmente, non per quelle partizionate su base oraria, mensile o annuale.

Partizionamento delle colonne per unità di tempo

Quando esegui lo streaming in una tabella partizionata per colonna di unità di tempo, BigQuery inserisce automaticamente i dati nella partizione corretta in base ai valori della colonna di partizionamento predefinita DATE, DATETIME o TIMESTAMP della tabella. Puoi trasmettere dati in una tabella partizionata per colonna di unità di tempo se i dati a cui fa riferimento la colonna di partizionamento sono compresi 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 intervalli 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 i dati in streaming. Fluent Bit è un processore e 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 at-least-once che utilizza il tipo predefinito.
  • Semantica exactly-once che utilizza il tipo committed.
  • Scalabilità dinamica per gli stream predefiniti, quando viene indicata la contropressione.

Supporto di Apache Iceberg

Puoi utilizzare l'API Storage Write (gRPC) per inserire flussi di dati nelle tabelle Iceberg. Per saperne di più, consulta Tabelle gestite Apache Iceberg.

Metriche di progetto dell'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 metricheGoogle Cloud .

Utilizza data manipulation language (DML) con i dati trasmessi in streaming di recente

Puoi utilizzare 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 saperne di più sull'utilizzo di DML per modificare i dati in streaming, consulta Utilizzo del linguaggio di manipolazione dei dati.

Limitazioni

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

Esegui query sui dati in streaming con max_staleness

Per impostazione predefinita, ogni volta che esegui una query su una tabella con dati in streaming, BigQuery restituisce i risultati più recenti e aggiornati includendo le righe trasmesse in streaming fino al momento dell'esecuzione della query.

Se il tuo caso d'uso non richiede l'aggiornamento dei dati in tempo reale, ad esempio nelle dashboard o nelle query di generazione di report, puoi ridurre la latenza e il costo delle query configurando l'obsolescenza dei dati. Per configurare l'obsolescenza dei dati, utilizza uno dei seguenti metodi:

  • Configura l'obsolescenza a livello di tabella (CDC o viste materializzate): imposta l'opzione max_staleness sulla tabella di destinazione per consentire alle query di restituire risultati basati su snapshot di dati recenti entro l'intervallo di obsolescenza. Per maggiori informazioni, consulta Change Data Capture max_staleness e Viste materializzate con max_staleness.
  • Esegui l'override dell'obsolescenza per una query o una sessione: imposta la variabile di sistema @@max_staleness_override nella query o nella sessione con più istruzioni per eseguire l'override dell'obsolescenza in modo dinamico senza modificare le configurazioni a livello di tabella, ad esempio SET @@max_staleness_override = INTERVAL 10 MINUTE;.

Quote dell'API Storage Write (gRPC)

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

Puoi monitorare l'utilizzo della quota di connessioni simultanee e di throughput nella pagina Quote della consoleGoogle Cloud .

Calcola il throughput

Supponiamo che il tuo obiettivo sia raccogliere i log da 100 milioni di endpoint,creando 1500 record di log al minuto. Poi, 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 per l'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 snelli questi endpoint consiste nell'inviare gli eventi a Pub/Sub, da dove vengono utilizzati da una pipeline Dataflow in modalità flusso che trasmette direttamente a BigQuery.

Un problema principale di affidabilità 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 flussi di dati BigQuery con backoff esponenziale troncato. Una volta esaurita la capacità di Pub/Sub come buffer, ad esempio in caso di indisponibilità prolungata di BigQuery o di un errore di rete, i dati devono essere conservati sul client e il client deve disporre di un meccanismo per riprendere l'inserimento dei record conservati una volta ripristinata la disponibilità. Per saperne di più su come gestire questa situazione, consulta il blog post Guida all'affidabilità di Google Pub/Sub.

Un altro caso di errore da gestire è quello di un record non valido. Un record non valido è un record rifiutato da BigQuery perché non è stato possibile inserirlo con un errore non ripetibile o un record che non è stato inserito correttamente dopo il numero massimo di tentativi. Entrambi i tipi di record devono essere archiviati 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 i duplicati, poiché l'operazione di scrittura viene eseguita solo se il valore dell'offset corrisponde all'offset di aggiunta successivo. Se non viene fornito un offset, i record vengono aggiunti alla fine corrente dello stream e un nuovo tentativo di aggiunta non riuscita potrebbe comportare la visualizzazione del record più di una volta nello stream.

Se non sono richieste garanzie di tipo exactly-once, 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 gestire il throughput.

Se il tuo workload genera o elabora dati a una frequenza molto irregolare, prova ad attenuare eventuali picchi di carico sul client e a trasmettere in streaming in BigQuery con un throughput costante. In questo modo, puoi semplificare la pianificazione della capacità. Se non è possibile, assicurati di essere in grado di gestire gli errori 429 (risorsa esaurita) se e quando il throughput supera la quota durante brevi picchi.

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

Passaggi successivi