Lo sharding del database è una strategia utilizzata per risolvere i problemi di scalabilità nelle applicazioni che hanno una quantità massiccia di dati. Implica la suddivisione di un singolo set di dati logico di grandi dimensioni in parti più piccole e più gestibili chiamate shard. Ogni shard viene archiviato su un'istanza di server di database separata, distribuendo in modo efficace i dati e il workload su più macchine.
Lo sharding è un metodo chiave per la scalabilità orizzontale (scale out). Invece di eseguire l'upgrade di un singolo server con più CPU o RAM (scalabilità verticale), che alla fine raggiunge un limite hardware, lo sharding consente di aggiungere più server di base al cluster. Ciò consente alle applicazioni di gestire una crescita quasi infinita del volume di dati e del traffico utenti.
Sebbene lo sharding sia un modo efficace per fare lo scale out, è una delle tre strategie comuni di scalabilità orizzontale:
Lo sharding del database funziona raggruppando i dati in base a un valore specifico chiamato chiave di shard. Una chiave di shard è una colonna nel database, ad esempio un ID utente, una regione cliente o un numero di ordine, che determina quale server memorizzerà una riga di dati specifica. Quando i dati vengono scritti nel database, il sistema esamina questa chiave per decidere dove devono essere inseriti.
Per trovare i dati in un secondo momento, il sistema deve instradare la query nella posizione corretta. Questo routing avviene in due modi principali:
Poiché prende di mira solo lo shard pertinente, il database risponde alle query più velocemente e gestisce migliaia di richieste simultanee senza rallentare.

Applicazioni diverse richiedono logiche diverse per la suddivisione dei dati. Il metodo scelto determina il modo in cui il "livello di routing" trova i tuoi dati.
Questo metodo utilizza una formula matematica (una funzione hash) sulla chiave di shard per assegnare i dati. Ad esempio, il sistema potrebbe calcolare l'ID utente (mod 4) per assegnare un utente a uno dei 4 server.
Sebbene le funzioni hash aiutino a distribuire i dati in modo coerente, garantiscono una distribuzione uniforme solo se la chiave di shard ha una cardinalità elevata e una bassa asimmetria di frequenza. Se scegli una chiave di shard con un valore comune, ad esempio "Cognome" in cui "Rossi" compare 1000 volte più di "Bianchi", la funzione hash invierà ogni record "Rossi" allo stesso shard. In questo modo viene creato un "hot shard" nonostante l'uso di una formula matematica.
L'aggiunta di nuovi server è difficile con questo metodo perché la formula cambia, il che spesso richiede di "ricondividere" o spostare i dati nel nuovo cluster di server.
I dati vengono assegnati in base a intervalli di valori. Ad esempio, potresti inserire gli ID utente 1-1000 sul server A e 1001-2000 sul server B. È molto intuitivo e ottimo per le query che devono leggere una sequenza di dati (query di intervallo). Lo svantaggio è la creazione di "hotspot": se tutti i nuovi utenti vengono assegnati al server B, questo server svolgerà tutto il lavoro mentre il server A rimarrà inattivo.
Questa strategia utilizza una tabella di ricerca (una directory) che tiene traccia di quale shard contiene quali dati. Offre la massima flessibilità perché puoi spostare i dati tra gli shard senza modificare una formula. Tuttavia, questa tabella di ricerca diventa un collo di bottiglia: ogni query deve controllare prima la directory, aggiungendo latenza. Se la directory non funziona, l'intero database diventa inaccessibile.
Lo sharding geografico assegna i dati a server specifici in base alla posizione fisica di un utente. Ad esempio, i dati degli utenti in Francia vengono archiviati su server nell'UE, mentre gli utenti statunitensi si trovano su server in Nord America. Ciò riduce significativamente la latenza (velocità) per gli utenti e aiuta le aziende a rispettare le leggi sulla residenza dei dati come il GDPR.
A volte chiamata partizionamento funzionale, questa tecnica prevede la suddivisione dei dati per funzionalità anziché per riga. Ad esempio, potresti posizionare tutte le tabelle "Profilo utente" sul server A e tutte le tabelle "Caricamento foto" sul server B. Sebbene ciò organizzi i dati in modo logico, è funzionalmente simile a un'architettura di dati per microservizi e non risolve il problema se una funzionalità specifica (come Foto) diventa troppo grande per un singolo server.
La scelta della chiave di shard corretta è la decisione più critica nello sharding. Una chiave errata può portare a una distribuzione dei dati non uniforme (hot spot), mentre una chiave corretta può garantire che tutti i server funzionino allo stesso modo. Per ottimizzare questo aspetto, devi considerare tre fattori:
Sebbene questi termini vengano spesso usati insieme nella progettazione di sistemi, risolvono problemi diversi.
Lo sharding è un tipo specifico di partizionamento orizzontale in cui le parti di dati vengono distribuite su server completamente diversi. In questo modo si risolvono sia i limiti di capacità hardware (archiviazione) sia i colli di bottiglia della velocità effettiva di scrittura, poiché server diversi possono elaborare le scritture contemporaneamente.
Il partizionamento prevede la suddivisione di una tabella di grandi dimensioni in parti più piccole e gestibili (come la suddivisione di una tabella di log per mese), mantenendole però sulla stessa istanza del server. Questo risolve i problemi di archiviazione semplificando l'archiviazione o l'eliminazione di dati obsoleti senza influire sul resto della tabella. Tuttavia, non risolve i problemi del server. Poiché tutte le partizioni risiedono ancora su una singola macchina, continuano a condividere la stessa CPU e la stessa RAM, il che significa che il partizionamento non può essere d'aiuto se il server raggiunge i suoi limiti di prestazioni.
La replica è il processo di copia dell'intero database su più server. Può essere una buona scelta per la disponibilità di lettura: se un server non funziona, un altro può subentrare. Tuttavia, non aiuta con la scalabilità della scrittura perché ogni dato scritto deve essere copiato in ogni replica, limitando la velocità di scrittura alla capacità di una singola macchina.
Altrettanto importante è il fatto che la maggior parte dei modelli di replica consente un solo "writer" (scrittore, ovvero il nodo primario) alla volta. Se tenti di consentire a più server di accettare scritture contemporaneamente, rischi conflitti di scrittura, in cui due server tentano di aggiornare lo stesso record con informazioni diverse. La risoluzione di questi conflitti è tecnicamente difficile e può portare alla perdita o all'incoerenza dei dati se non viene gestita da un sistema distribuito sofisticato.
Un database distribuito, come Spanner, offre i vantaggi dello sharding senza il sovraccarico manuale. Questi sistemi sono progettati per essere distribuiti su un cluster di macchine fin dall'inizio. Gestiscono automaticamente la distribuzione, il ribilanciamento e la replica dei dati in modo trasparente. Alcuni di questi sistemi hanno più writer e gestiscono automaticamente i conflitti di scrittura. Ciò consente di scalare orizzontalmente mantenendo la coerenza di un database relazionale tradizionale.
Utilizza la tabella seguente per comprendere le differenze tra questi concetti di base del database.
Funzionalità | Sharding | Partizionamento | Replica | Database distribuito |
Obiettivo principale | Archiviazione e scalabilità di scrittura massiccia | Gestibilità e manutenzione | Alta affidabilità e scalabilità di lettura | Scalabilità globale automatizzata |
Località dei dati | Diversi blocchi di dati su server diversi | Diversi chunk di dati sullo stesso server | Copie degli stessi dati su più server | Gestito in un cluster |
Prestazioni di scrittura | Miglioramento elevato (le scritture avvengono in parallelo) | Miglioramento minore (indici più piccoli) | Nessun miglioramento (le scritture devono andare a tutte le copie) | Miglioramento elevato |
complessità | Elevata | Media | Bassa | Bassa (gestita) |
Funzionalità
Sharding
Partizionamento
Replica
Database distribuito
Obiettivo principale
Archiviazione e scalabilità di scrittura massiccia
Gestibilità e manutenzione
Alta affidabilità e scalabilità di lettura
Scalabilità globale automatizzata
Località dei dati
Diversi blocchi di dati su server diversi
Diversi chunk di dati sullo stesso server
Copie degli stessi dati su più server
Gestito in un cluster
Prestazioni di scrittura
Miglioramento elevato (le scritture avvengono in parallelo)
Miglioramento minore (indici più piccoli)
Nessun miglioramento (le scritture devono andare a tutte le copie)
Miglioramento elevato
complessità
Elevata
Media
Bassa
Bassa (gestita)
Lo sharding può spesso essere l'unica soluzione praticabile per le applicazioni che gestiscono terabyte di dati o milioni di transazioni al secondo.
Scalabilità orizzontale
Lo sharding consente una scalabilità quasi infinita aggiungendo server standard a un cluster. In questo modo si evita la "tassa dell'hardware" delle applicazioni legacy con scalabilità verticale. Senza lo sharding, spesso sei costretto ad acquistare hardware costoso e specializzato che raggiunge un limite di prestazioni. Lo sharding consente al database di crescere insieme alla tua attività utilizzando macchine più convenienti e di base
Prestazioni delle query migliorate
Lo sharding velocizza le singole query perché ogni server cerca in un set di dati più piccolo. Invece di cercare in un indice di 100 milioni di righe, una query potrebbe dover cercare solo in uno shard con 1 milione di righe. Inoltre, poiché i dati si trovano su macchine diverse, puoi eseguire più query in parallelo, aumentando notevolmente la velocità effettiva totale dell'applicazione.
Affidabilità
Lo sharding limita il "raggio di impatto" di un errore. Se uno shard non funziona, solo gli utenti interessati ne risentono, mentre il resto dell'app rimane online. Tuttavia, un numero maggiore di server comporta un maggiore carico amministrativo. La gestione di backup, sicurezza e patch su decine di istanze aumenta la complessità operativa rispetto a una configurazione a server singolo.
Sebbene lo sharding risolva i requisiti di scalabilità massiccia, introduce compromessi tecnici e operativi significativi. Dovresti considerare queste sfide prima di abbandonare un'architettura a istanza singola.
Google Cloud offre soluzioni di database che eliminano il lavoro pesante dello sharding manuale, consentendoti di concentrarti sulla creazione della tua applicazione anziché sulla gestione dell'infrastruttura.


