Best practice per l'API BigQuery Storage Write (gRPC)
Puoi massimizzare il throughput di scrittura ed evitare colli di bottiglia della quota con l'API BigQuery Storage Write (gRPC) ottimizzando il modo in cui la tua applicazione crea stream, raggruppa le connessioni e raggruppa le richieste batch. Anche un'attenta gestione degli offset e degli aggiornamenti degli schemi aiuta a mantenere resilienti le pipeline di importazione man mano che gli schemi delle tabelle si evolvono. Per i concetti di base dei flussi, consulta Panoramica dell'API BigQuery Storage Write (gRPC).
Limita la frequenza di creazione degli stream
Prima di creare uno stream, valuta se puoi utilizzare lo stream predefinito. Per gli scenari di streaming, lo stream predefinito ha meno limitazioni di quota e può scalare meglio rispetto all'utilizzo di stream creati dall'applicazione. Se utilizzi un flusso creato dall'applicazione, assicurati di utilizzare il throughput massimo su ogni flusso prima di crearne altri. Ad esempio, utilizza le scritture asincrone.
Per gli stream creati dall'applicazione, evita di chiamare CreateWriteStream con una frequenza elevata. In genere, se superi le 40-50 chiamate al secondo, la latenza delle chiamate API aumenta notevolmente (>25 s). Assicurati che la tua applicazione possa accettare un avvio a freddo e aumentare gradualmente il numero di stream, nonché limitare la frequenza delle chiamate CreateWriteStream. Puoi anche impostare una scadenza più lunga per attendere il completamento della chiamata, in modo che non si verifichi un errore DeadlineExceeded. Esiste anche una quota a lungo termine sulla frequenza massima delle chiamate CreateWriteStream. La creazione di stream è un processo che richiede molte risorse, quindi ridurre la frequenza di creazione degli stream e utilizzare appieno gli stream esistenti è il modo migliore per non superare questo limite.
Gestione del pool di connessioni
Il metodo AppendRows crea una connessione bidirezionale a uno stream. Puoi aprire più connessioni sullo stream predefinito, ma solo una singola connessione attiva sugli stream creati dall'applicazione.
Quando utilizzi lo stream predefinito, puoi utilizzare il multiplexing dell'API Storage Write (gRPC) per scrivere in più tabelle di destinazione con connessioni condivise. Il multiplexing raggruppa le connessioni per migliorare il throughput e l'utilizzo delle risorse. Se il tuo workflow ha più di 20 connessioni simultanee, ti consigliamo di utilizzare il multiplexing. Il multiplexing è disponibile in Java e Go. Per i dettagli sull'implementazione di Java, consulta Utilizza il multiplexing. Per i dettagli sull'implementazione di Go, consulta Condivisione della connessione (multiplexing). Se utilizzi il connettore Beam con semantica at-least-once, puoi attivare il multiplexing tramite UseStorageApiConnectionPool. Il connettore Managed Service for Apache Spark ha il multiplexing abilitato per impostazione predefinita.
Per ottenere prestazioni ottimali, utilizza una connessione per il maggior numero possibile di scritture di dati. Non utilizzare una connessione per una singola scrittura o aprire e chiudere stream per molte piccole scritture.
Esiste una quota sul numero di connessioni simultanee che possono essere aperte contemporaneamente per progetto. Al di sopra del limite, le chiamate a AppendRows non vanno a buon fine.
Tuttavia, la quota per le connessioni simultanee può essere aumentata e normalmente non dovrebbe essere un fattore limitante per la scalabilità.
Ogni chiamata a AppendRows crea un nuovo oggetto DataWriter. Pertanto, quando utilizzi uno stream creato dall'applicazione, il numero di connessioni corrisponde al numero di stream creati. 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, ma può superare i 10 MBps.
Esiste anche una quota sul throughput totale per progetto. Rappresenta i byte al secondo in tutte le connessioni che passano attraverso il servizio API Storage Write (gRPC). Se il tuo progetto supera questa quota, puoi richiedere un aggiustamento della quota. In genere, ciò comporta l'aumento delle quote di accompagnamento, come la quota di connessioni simultanee, in un rapporto uguale.
Gestisci gli offset degli stream per ottenere la semantica exactly-once
L'API Storage Write (gRPC) consente solo scritture alla fine corrente dello stream, che si sposta man mano che i dati vengono aggiunti. La posizione corrente nello stream è specificata come offset dall'inizio dello stream.
Quando scrivi in uno stream creato dall'applicazione, puoi specificare l'offset dello stream per ottenere una semantica di scrittura exactly-once.
Quando specifichi un offset, l'operazione di scrittura è idempotente, il che rende sicuro riprovare in caso di errori di rete o di mancata risposta del server. Gestisci i seguenti errori relativi agli offset:
ALREADY_EXISTS(StorageErrorCode.OFFSET_ALREADY_EXISTS): la riga è già stata scritta. Puoi ignorare questo errore.OUT_OF_RANGE(StorageErrorCode.OFFSET_OUT_OF_RANGE): un'operazione di scrittura precedente non è riuscita. Riprova dall'ultima scrittura riuscita.
Tieni presente che questi errori possono verificarsi anche se imposti un valore di offset errato, quindi devi gestire gli offset con attenzione.
Prima di utilizzare gli offset di stream, valuta se hai bisogno della semantica "exactly-once". Ad esempio, se la pipeline di dati upstream garantisce solo scritture at-least-once o se puoi rilevare facilmente i duplicati dopo l'importazione dati, potresti non aver bisogno di scritture exactly-once. In questo caso, ti consigliamo di utilizzare lo stream predefinito, che non richiede di tenere traccia degli offset di riga.
Non bloccare le chiamate di AppendRows
Il metodo AppendRows è asincrono. Puoi inviare una serie di scritture senza bloccare una risposta per ogni singola scrittura. I messaggi di risposta sulla connessione bidirezionale arrivano nello stesso ordine in cui le richieste sono state messe in coda.
Per ottenere il throughput più elevato, chiama AppendRows senza bloccare l'attesa della risposta.
Preferisci richieste più grandi
Esiste un overhead di elaborazione sia sul lato client sia sul lato server per ogni richiesta inviata. Per migliorare l'efficienza, invia richieste di grandi dimensioni (superiori a 1 MB) quando possibile.
Gestisci gli aggiornamenti dello schema
Per gli scenari di flussi di dati, gli schemi delle tabelle vengono solitamente gestiti al di fuori della pipeline di streaming. È comune che lo schema si evolva nel tempo, ad esempio aggiungendo nuovi campi nullable. Una pipeline solida deve gestire gli aggiornamenti dello schema fuori banda.
L'API Storage Write (gRPC) supporta gli schemi delle tabelle come segue:
- La prima richiesta di scrittura include lo schema.
- Invia ogni riga di dati come buffer di protocollo binario. BigQuery mappa i dati allo schema.
- Puoi omettere i campi che ammettono valori null, ma non puoi includere campi non presenti nello schema corrente. Se invii righe con campi aggiuntivi, l'API Storage Write (gRPC) restituisce un
StorageErrorconStorageErrorCode.SCHEMA_MISMATCH_EXTRA_FIELD.
Se vuoi inviare nuovi campi nel payload, devi prima aggiornare lo schema della tabella in BigQuery. L'API Storage Write (gRPC) rileva le modifiche allo schema dopo un breve periodo di tempo, nell'ordine di minuti. Quando l'API Storage Write (gRPC) rileva la modifica dello schema, il messaggio di risposta AppendRowsResponse contiene un oggetto TableSchema che descrive il nuovo schema.
Per inviare dati utilizzando lo schema aggiornato, devi chiudere le connessioni esistenti e aprirne di nuove con il nuovo schema.
Client Java. La libreria client Java fornisce alcune funzionalità aggiuntive per gli aggiornamenti dello schema tramite la classe JsonStreamWriter. Dopo un aggiornamento dello schema, JsonStreamWriter si ricollega automaticamente allo schema aggiornato. Non è necessario chiudere e riaprire esplicitamente la connessione.
Per verificare la presenza di modifiche allo schema in modo programmatico, chiama
AppendRowsResponse.hasUpdatedSchema dopo il completamento del metodo
append.
Puoi anche configurare JsonStreamWriter in modo che ignori i campi sconosciuti nei dati di input. Per impostare questo comportamento, chiama
setIgnoreUnknownFields. Questo comportamento è simile
all'opzione ignoreUnknownValues quando utilizzi
l'API BigQuery Storage Write (REST).
Tuttavia, può portare alla perdita involontaria di dati, perché i campi sconosciuti vengono ignorati senza preavviso.