3 min read

Database ID, scalabili, unici, offuscati o corti ?

Sembra un po' il dilemma della "Patatina di Rocco Siffredi", se non fosse che girovagando su internet si trovano un mucchio di siti "404 Not Found" e la gran parte delle volte non accade perché quella pagina è stata realmente cancellata, ma perché durante un cambio di DNS, CMS, DB, blog,.. qualcosa è andato storto e quindi la pagina in questione è andata persa, forse sempre. A volte si può provare recuperare qualcosa inserendo l'URL su Google e ravanare nella sua cache, ma diciamo che è più un'eccezione che la regola.

Sicuramente ogni volta che accade il 404 non faccio che pensare "ma che razza di esperto è uno che vuole gestire i siti degli altri e non sa gestire il proprio?" oppure "possibile che si può leggere un papiro egizio di 5000 anni fa e non si riesce a mantenere i riferimenti a un documento di 3 anni fa su un sito?"

Per chi non avesse ancora capito, l'argomento del post è dedicato a questi "misteriosi" riferimenti che si chiamano identificatori o per gli amici "id". Chi ha studiato database e le proprietà ACID all'università saprà che ogni tabella ne ha almeno uno che deve essere unico per ogni record che contiene, per tutti gli altri sappiate che l'ultima parte del sito ( es. "......../345/cippalippa") è importantissima per identificare la pagina che state vedendo.

Ad ogni modo esistono vari tipi di id per esigenze diverse e che se li pianificate male la vostra infrastruttura informatica potrebbe risentirne pesantemente e la cosa peggiore che può capitarvi è dover cambiare la struttura di un database improvvisamente con il database in funzione.
Quindi lasciamo stare gli aspetti prettamente teorici e accademici e concentriamoci su quelli pratici, giusto per non ripetere gli errori che alcuni colossi del web hanno fatto (es Twitter) perché "In pratica la teoria è un'altra cosa".

I tipi di database id e cosa rappresentano su vari siti importanti:

ID INTEGER 32 o 64bit AUTO INCREMENT

Si tratta del tipo di chiave primaria di default, il più utilizzato e il più accademico. Esempio, abbiamo la tabella prodotti e la tabella categorie, la prima tabella mantiene il riferimento alla categoria attraverso il campo cagoria_id, quindi abbiamo dei record del tipo ["tonno", 3] e [3, "pesce"]. Quando inseriamo un nuovo record questo avrà un id aumentato di una unità.
Formato URL: miosito/23-pizza | miosito/users/23 | miosito/users/23/pizza.html
PRO: funziona out-of-the-box, facile debug
CONTRO: non scala bene, se l'infrastruttura web ha molte richieste in scrittura simultanee c'é il rischio che 2 db diversi generino lo stesso ID.
Se il sito ha successo c'é il rischio quasi certo di site scraping non autorizzato perché è banale trovare un id successivo partendo da uno valido (+1).
Per citare un esempio il noto sito di domande e risposte Stackoverflow.com è sistematicamente copiato da efreedom.com

In ruby i numeri possono essere rappresentati in molti modi e quindi convertiti 21, 2_000_000_000

"21-patate-croccanti".to_i
=> 21

 

ID corto in Base64 o Base62 alla bit.ty

Dal punto di vista pratico non cambia molto dal precedente, se non fosse che invece della base decimale si usa una base diversa.
PRO: è più corto
CONTRO: come sopra

In Rails con Ruby 1.8.7 si può usare il metodo encode64s della libreria ActiveSupport altrimenti in ruby >=1.9.x c'é il supporto nel linguaggio ruby stesso. La differenza principale tra base32, base64 o base64-safe è che nella prima e nella terza non compaiono caratteri fastidiosi come "/","=".

Esempio con base32

      1000000023214325423454361234567800000000.to_s(32)
=> "nga3vrh2mbj50hn0ckjmsgf3g0"
"nga3vrh2mbj50hn0ckjmsgf3g0".to_i(32)
=> 1000000023214325423454361234567800000000

GUID o UUID

Si tratta di stringhe random-casuali, Global Unique Identifier o Universally Unique Identifier, se vi fidate del vostro computer e della matematica la possibilità di generare collisioni o stringhe uguali è molto remota (ma non impossibile). C'é anche un generatore di UUID online.
PRO: i dati possono essere scritti in db differenti e poi possono sincronizzarsi in un secondo momento.
CONTRO: non sono sequenziali (dovete avere per forza un campo datetime se le volete ordinare), difficile ricordarsele a memoria :P

Best Practices, ibrido e casi reali

Le banche sono dei grandissimi consumatori di id e hanno trovato il loro compromesso col sistema IBAN che è un ibrido di varie componenti temporali e sequenziali.
Twitter usa come identificatori le stringhe case sensitive per gli utenti, mentre usa un id sequenziale per i tweet, ma passeranno presto a un sistema di id ibrido timestamp + worker number + sequence number (non senza soprese, perché potrebbe avere delle ripercussioni se le API vengono usate via javascript). Maggiori info sul sistema Snowflake
FriendFeed usa un id UUID e Mysql in "modalità" NOSQL schemaless.
Facebook usa un sistema sequenziale per i profili utente /profile.php?id=12945833XX ma a quanto pare non sequenziale per i messaggi e gli eventi /event.php?eid=1608597906110XX
Yahoo! Answers usa questo schema 20101129092747AAJ1RXX che a occhio dovrebbe essere data più qualche dato sequenziale.

In conclusione che dire? Praticità e semplicità immediata non vanno a braccetto con SEO, scalabilità o mantenibilità nel tempo, quindi pensateci.