CodeGym /Corsi /SQL SELF /Generazione di identificatori unici

Generazione di identificatori unici

SQL SELF
Livello 16 , Lezione 0
Disponibile

Generazione di identificatori unici

Quando i computer hanno iniziato a connettersi attivamente in rete, è sorto un problema semplice ma molto urgente: come garantire che due dispositivi diversi, situati in parti diverse del mondo, non generino lo stesso identificatore?

Immagina: due server, uno a Tokyo e uno a Berlino, creano indipendentemente identificatori per oggetti. Se per caso generano lo stesso ID — i dati possono confondersi, sovrascriversi, e il sistema può andare in crash.

Così, negli anni '90, nell'epoca dello sviluppo esplosivo dei sistemi distribuiti e dei protocolli di rete, nei laboratori di Microsoft e Open Software Foundation (OSF) è nata l'idea del GUIDGlobally Unique Identifier, cioè identificatore globale unico.

Il GUID (e nello standard ISO — UUID, Universally Unique Identifier) è un numero a 128 bit, che appare, ad esempio, così:

550e8400-e29b-41d4-a716-446655440000

È come un'impronta digitale digitale: è così lungo e caotico che la probabilità di collisione (due identificatori uguali) è praticamente nulla.

Viene creato usando:

  • l'orario,
  • numeri casuali,
  • l'indirizzo MAC del dispositivo (nelle vecchie versioni),
  • e persino funzioni hash crittografiche.

Perché era importante? Il punto è che il GUID ha permesso di creare identificatori unici senza server centrale, senza coordinazione, senza lock e senza ritardi. È stata una vera salvezza per:

  • database distribuiti,
  • protocolli di rete,
  • sistemi di gestione documentale,
  • e ovviamente le moderne API.

UUID in PostgreSQL

GUID/UUID si usano ovunque — da PostgreSQL ai servizi cloud. Sono diventati i costruttori invisibili di Internet moderno: senza di loro non potremmo collegare il mondo così facilmente.

In pratica è solo un numero casuale molto lungo di 16 byte, scritto in formato esadecimale. Semplicemente un intero molto lungo.

Questo tipo di dato è perfetto se vuoi garantire l'unicità dei valori a livello di tutto il sistema, senza dipendere da un generatore centralizzato di identificatori. È particolarmente utile nei sistemi distribuiti o quando i dati vengono generati su server diversi.

Perché non usare semplicemente INTEGER?

Verrebbe da chiedersi, perché serve UUID se si può usare un numero auto-incrementale come identificatore? Vediamo insieme:

Unicità globale: Se il tuo database gira su più server, garantire l'unicità di INTEGER è difficile. Con UUID il problema sparisce.

Sicurezza e offuscamento dati: UUID è più difficile da indovinare rispetto a un numero sequenziale. Questo riduce il rischio di leak di informazioni tramite identificatori prevedibili (tipo /users/1, /users/2).

Sistemi distribuiti: Se i dati vengono generati in parti diverse del sistema, un INTEGER auto-incrementale non va bene senza una sincronizzazione complicata.

Un altro vantaggio di UUID — è uno standard supportato in tanti linguaggi di programmazione e sistemi di storage.

Vantaggi dell'uso di UUID

I principali pro:

  • Unicità: garantisce l'unicità dell'identificatore, anche se i dati vengono creati su server o sistemi diversi.
  • Flessibilità: puoi usarlo per chiavi primarie, chiavi esterne e altri scopi.
  • Scalabilità: comodissimo quando lavori con database distribuiti.

Però UUID ha anche i suoi svantaggi:

  • Dimensione: UUID occupa più spazio in memoria (16 byte) rispetto a INTEGER (4 byte).
  • Leggibilità: è relativamente più difficile da leggere e ricordare.

Generazione di UUID in PostgreSQL

Funzione integrata gen_random_uuid()

In PostgreSQL dalla versione 13 c'è la funzione integrata gen_random_uuid() per generare UUID casuali. Questa funzione restituisce un identificatore unico che puoi usare come valore per una colonna di tipo UUID.

Esempio:

SELECT gen_random_uuid();

Risultato:

d17fc23b-22e5-4fcb-bf86-1b4c766d77b7

Assicurati che l'estensione pgcrypto sia installata (per PSQL 1-12)

Nelle versioni precedenti di PostgreSQL (fino alla 12) la funzione gen_random_uuid() è disponibile dopo aver installato l'estensione pgcrypto. Se al lavoro ti obbligano a usarla, puoi salvare la situazione eseguendo il comando:

CREATE EXTENSION IF NOT EXISTS "pgcrypto";

Questo ti permetterà di usare la generazione di UUID casuali.

Uso di UUID come chiave esterna

UUID è comodissimo per creare relazioni tra tabelle. Supponiamo tu abbia una tabella utenti:

id name email
d17fc23b-22e5-4fcb-bf86-1b4c766d77b7 Alice alice@example.com
a1d3e15a-abc1-4b51-a320-2d4c859f7467 Bob bob@example.com
3c524998-5c24-4e73-836d-a4c6bb3cafcd Charlie charlie@example.com

Creazione della tabella orders

Creiamo la tabella orders, dove user_id sarà una chiave esterna che punta a id nella tabella users.

order_id user_id order_date
1a5b7d9c-b1a2-4f8e-9e7a-0a1111111111 d17fc23b-22e5-4fcb-bf86-1b4c766d77b7 2024-10-15 10:00:00
2b6c8e0d-c2b3-5a9f-af8b-1b2222222222 a1d3e15a-abc1-4b51-a320-2d4c859f7467 2024-10-15 10:05:00
3c7d9f1e-d3c4-6baf-bc9c-2c3333333333 3c524998-5c24-4e73-836d-a4c6bb3cafcd 2024-10-15 10:10:00
4d8eaf2f-e4d5-7cb0-cdab-3d4444444444 d17fc23b-22e5-4fcb-bf86-1b4c766d77b7 2024-10-15 10:15:00
5e9fb030-f5e6-8dc1-debc-4e5555555555 a1d3e15a-abc1-4b51-a320-2d4c859f7467 2024-10-15 10:20:00

Il campo user_id è collegato al campo id della tabella users, così puoi creare relazioni tra utenti e i loro ordini.

Query con JOIN

Vediamo come sono collegati i dati nelle tabelle users e orders:

SELECT 
    u.id AS user_id, 
    u.name, 
    o.order_id, 
    o.order_date 
FROM users u
JOIN orders o ON u.id = o.user_id;

Risultato:

user_id name order_id order_date
d17fc23b-22e5-4fcb-bf86-1b4c766d77b7 Alice a1d3e15a-abc1-4b51-a320-2d4c859f7467 2024-10-20 12:34:56

Principali scenari d'uso di UUID

Identificatori di utenti e ordini: nei sistemi distribuiti, dove i dati possono arrivare da fonti diverse.

Etichette per API: UUID viene spesso usato nelle REST API per identificare le entità.

Sincronizzazione globale dei dati: ad esempio, quando i dati vengono raccolti da server diversi.

Errori tipici e particolarità

Tentativo di generare UUID a mano: meglio usare le funzioni integrate, tipo gen_random_uuid(), per evitare errori.

Uso eccessivo: non usare UUID dove basta un INTEGER auto-incrementale. Per esempio, in tabelle locali che non saranno mai scalate.

Dimensione: UUID occupa più spazio, il che può influire sulle performance delle query, soprattutto sugli indici.

Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION