Best practice per il caricamento collettivo

Questa pagina fornisce linee guida per il caricamento collettivo efficiente di grandi quantità di dati in Spanner.

Esistono diverse opzioni per caricare in blocco i dati in Spanner:

Anche se puoi anche inserire righe utilizzando Google Cloud CLI, non ti consigliamo di utilizzare gcloud CLI per il caricamento collettivo.

Linee guida sul rendimento per il caricamento collettivo

Per ottenere prestazioni ottimali per il caricamento collettivo, massimizza l'utilizzo del partizionamento per distribuire la scrittura dei dati tra le attività dei worker.

Spanner utilizza la suddivisione in base al carico per distribuire uniformemente il carico di dati sulle risorse di calcolo dell'istanza. Dopo alcuni minuti di carico elevato, Spanner introduce confini suddivisi tra le righe. In generale, se il caricamento dei dati è ben distribuito e segui le best practice per la progettazione dello schema e il caricamento collettivo, il throughput in scrittura dovrebbe raddoppiare ogni pochi minuti fino a saturare le risorse CPU disponibili nell'istanza.

Partiziona i dati in base alla chiave primaria

Spanner partiziona automaticamente le tabelle in intervalli più piccoli. La chiave primaria per una riga determina dove viene partizionata.

Per ottenere un throughput di scrittura ottimale per i caricamenti collettivi, partiziona i dati in base alla chiave primaria con questo pattern:

  • Ogni partizione contiene un intervallo di righe consecutive, come stabilito dalle colonne chiave.
  • Ogni commit contiene dati per una sola partizione.

Ti consigliamo di impostare il numero di partizioni su 10 volte il numero di nodi della tua istanza Spanner. Per assegnare le righe alle partizioni:

  • Ordina i dati in base alla chiave primaria.
  • Suddividi i dati in 10 * (numero di nodi) partizioni separate di dimensioni uguali.
  • Crea e assegna un'attività di worker separata a ogni partizione. La creazione delle attività dei worker avviene nella tua applicazione. Non è una funzionalità di Spanner.

Seguendo questo schema, dovresti ottenere una velocità effettiva massima di scrittura collettiva di 10-20 MB al secondo per nodo per carichi elevati.

Man mano che carichi i dati, Spanner crea e aggiorna le suddivisioni per bilanciare il carico sui nodi dell'istanza. Durante questa operazione, potresti riscontrare temporanei cali della produttività.

Esempio

Hai una configurazione regionale con 3 nodi. Hai 90.000 righe in una tabella non interlacciata. Le chiavi principali nella tabella vanno da 1 a 90000.

  • Righe: 90.000 righe
  • Nodi: 3
  • Partizioni: 10 * 3 = 30
  • Righe per partizione: 90000 / 30 = 3000.

La prima partizione include l'intervallo di chiavi da 1 a 3000. La seconda partizione include l'intervallo di chiavi da 3001 a 6000. La 30a partizione include l'intervallo di chiavi da 87001 a 90000. Non devi utilizzare chiavi sequenziali in una tabella di grandi dimensioni. Questo esempio è solo a scopo dimostrativo.

Ogni attività di worker invia le scritture per una singola partizione. All'interno di ogni partizione, devi scrivere le righe in sequenza in base alla chiave primaria. La scrittura delle righe in modo casuale, rispetto alla chiave primaria, dovrebbe anche fornire un throughput ragionevolmente elevato. La misurazione delle esecuzioni di test ti fornirà informazioni sull'approccio che offre il rendimento migliore per il tuo set di dati.

Caricamento collettivo senza partizionamento

La scrittura di un insieme contiguo di righe in un commit può essere più veloce della scrittura di righe random. Le righe casuali includono probabilmente anche dati di partizioni diverse.

Quando vengono scritte più partizioni in un commit, è necessaria una maggiore coordinazione tra i server, aumentando la latenza e l'overhead del commit.

È probabile che siano coinvolte più partizioni perché ogni riga casuale potrebbe appartenere a una partizione diversa. Nel peggiore dei casi, ogni scrittura coinvolge ogni partizione dell'istanza Spanner. Come accennato in precedenza, la velocità effettiva di scrittura si riduce quando sono coinvolte più partizioni.

Evitare il sovraccarico

È possibile inviare più richieste di scrittura di quante Spanner possa gestire. Spanner gestisce il sovraccarico interrompendo le transazioni, operazione chiamata pushback. Per le transazioni di sola scrittura, Spanner ritenta automaticamente la transazione. In questi casi, il pushback viene visualizzato come latenza elevata. Durante i carichi elevati, il pushback può durare fino a un minuto. Durante i carichi molto elevati, il pushback può durare diversi minuti. Per evitare il pushback, devi limitare le richieste di scrittura per mantenere l'utilizzo della CPU entro limiti ragionevoli. In alternativa, gli utenti possono aumentare il numero di nodi in modo che l'utilizzo della CPU rimanga nei limiti.

Esegui il commit di un numero compreso tra 1 MB e 5 MB di mutazioni alla volta

Ogni scrittura in Spanner comporta un sovraccarico, indipendentemente dal fatto che sia di piccole o grandi dimensioni. Per massimizzare la velocità in bit, massimizza la quantità di dati archiviati per scrittura. Le scritture più grandi riducono il rapporto di overhead per scrittura. Una buona tecnica è che ogni commit modifichi centinaia di righe. Quando scrivi righe relativamente grandi, solitamente una dimensione del commit compresa tra 1 MB e 5 MB offre le migliori prestazioni. Quando scrivi valori piccoli o valori indicizzati, in genere è meglio scrivere al massimo alcune centinaia di righe in un singolo commit. Indipendentemente dalle dimensioni e dal numero di righe del commit, tieni presente che esiste un limite di 80.000 mutazioni per commit. Per determinare il rendimento ottimale, devi testare e misurare la velocità in bit.

I commit di dimensioni superiori a 5 MB o con più di alcune centinaia di righe non forniscono vantaggi aggiuntivi e rischiano di superare i limiti di Spanner per le dimensioni dei commit e le mutazioni per commit.

Linee guida per gli indici secondari

Se il database contiene indici secondari, devi scegliere se aggiungerli allo schema del database prima o dopo il caricamento dei dati della tabella.

  • L'aggiunta dell'indice prima del caricamento dei dati consente di completare immediatamente la modifica dello schema. Tuttavia, ogni scrittura che influisce sull'indice richiede più tempo poiché deve anche aggiornarlo. Al termine del caricamento dei dati, il database è subito utilizzabile con tutti gli indici in atto. Per creare contemporaneamente una tabella e i relativi indici, invia le istruzioni DDL per la nuova tabella e i nuovi indici in una singola richiesta a Spanner.

  • L'aggiunta dell'indice dopo il caricamento dei dati significa che ogni scrittura è efficiente. Tuttavia, la modifica dello schema per ogni riempimento dell'indice può richiedere molto tempo. Il database non è completamente utilizzabile e le query non possono utilizzare gli indici finché tutte le modifiche allo schema non sono state completate. Il database può comunque eseguire scritture e query, ma a una velocità inferiore.

Ti consigliamo di aggiungere gli indici fondamentali per la tua applicazione aziendale prima di caricare i dati. Aggiungi tutti gli indici non critici dopo la migrazione dei dati.

Testa e misura la velocità in bit

Prevedere il throughput può essere difficile. Ti consigliamo di testare la strategia di caricamento collettivo prima di eseguire il caricamento finale. Per un esempio dettagliato sull'utilizzo del partizionamento e del monitoraggio delle prestazioni, consulta Massimizzare il throughput del caricamento dei dati.

Best practice per il caricamento collettivo periodico in un database esistente

Se stai aggiornando un database esistente che contiene dati, ma non ha indici secondari, i consigli riportati in questo documento valgono comunque.

Se disponi di indici secondari, le istruzioni potrebbero produrre un rendimento ragionevole. Il rendimento dipende dal numero di suddivisioni, in media, coinvolte nelle tue transazioni. Se il throughput scende troppo, puoi provare quanto segue:

  • Includi un numero inferiore di mutazioni in ogni commit, il che potrebbe aumentare il throughput.
  • Se il caricamento è più grande delle dimensioni attuali totali della tabella aggiornata, elimina gli indici secondari e aggiungili di nuovo dopo aver caricato i dati. In genere questo passaggio non è necessario, ma potrebbe migliorare il throughput.