UUID con MySql InnoDB

UUID (Universal Unique Identifier) consente di generare un valore unico a livello globale poiche’ tale valore include sia informazioni sulla macchina che lo ha creato che sul timestamp del momento in cui e’ stato generato. I vantaggi di utilizzare questo valore come chiave primaria sono principalmente tre:

  • I record possono essere creati su device diversi dal db originale e mergiati o sincronizzati successivamente.
  • Non sara’ piu’ possibile cancellare record da tabelle diverse da quelle su cui pensavamo di agire.
  • Mette al riparo dallo scraping dei dati.

Il problema principale e’ che Mysql, nonostante abbia una funzione per generare un UUID, non gestisce i campi di tipo UUID come chiave primaria per le tabelle. In attesa che UUID sia disponibile nativamente su Mysql, con qualche piccolo accorgimento, e’ possibile comunque aggirare il problema. I due inconvenienti principali da risolvere per rendere l’ utilizzo di UUID efficace e performante al pari di una chiave primaria autoincrementale sono la dimensione dei dati e la sequenzialita’ dell’ indice.

Il primo problema deriva dal fatto che un UUID viene generato come una stringa di 36 caratteri esadecimali che quindi, se memorizzata come varchar, all’ aumentare dei record le tabelle iniziano ad occupare molto piu’ spazio di quanto occorre. Per risolvere questo problema e’ sufficiente memorizzare il dato come binario (16 bit) ed il primo problema e’ risolto. Sara’ sufficiente utilizzare HEX() ogni volta che effettuiamo una select sul nostro db (una chiave primaria non andrebbe mai modificata, ma se proprio nascesse la necessita’ di farlo esiste anche UNHEX()).

L’ altro problema e’ relativo alle prestazioni di Mysql in fase di inserimento. Le tabelle InnoDB memorizzano le chiavi primarie in maniera sequenziale, in pratica le chiavi devono essere in “ordine alfabetico” e il motore di Innodb si incarica di mantenerle in ordine. Indovinate… gli UUID non sono sequenziali!!! Di conseguenza, dopo ogni inserimento, InnoDB dovra’ riordinare l’ indice della tabella, cosa che ovviamente richiede risorse. Pero’, come abbiamo detto, UUID contiene alcuni valori derivati dal timestamp, che per definizione sono sicuramente sequenziali, quindi ci bastera’ modificare leggermente l’ ordine dell’ UUID per avere un valore sequenziale. La cosa piu’ pulita e’ di creare un trigger “after insert” che inserisca automaticamente per noi le chiavi primarie gia’ corrette.

Ecco fatto, il nostro MySql puo’ finalmente utilizzare gli UUID come chiave primaria. Se volete maggiori dettagli su questa implementazione qui e qui potete trovate ulteriori informazioni e i relativi benchmark.