UUID:t ja ULID:t ovat keinoja jakaa “globaalisti yksilöllisiä” tunnisteita hajautetuissa järjestelmissä ja tietokannoissa. Ne näyttävät ensisilmäyksellä samalta, mutta standardoinnin, tallennustehokkuuden, ihmisen luettavuuden ja tietovuotoriskin osalta eroja riittää. Tässä artikkelissa vertaan kolmea hallitsevaa lähestymistapaa – UUID v4:ää, UUID v7:ää ja ULID:ia – ja lopuksi kokoan huomioita myös UUID v1:stä ja UUID v6:sta.

Seuraavat työkalut hoitavat tunnisteiden luonnin ja aikaleimojen purun kokonaan selaimessa; käyttöliittymä on toistaiseksi japaniksi/englanniksi.


UUID v4: puhdas satunnaisuus

UUID v4 käyttää 122 bittiä 128 bitistä satunnaisuuteen, joten törmäyksen todennäköisyys on astronomisen pieni. Kääntöpuolena on, että arvot eivät järjesty aikajärjestykseen, jolloin B-puuindeksit hajoavat usein sivuiksi ja lisäysten paikallisuus kärsii. v4 sopii istuntotunnisteisiin, kertakäyttöisiin avaimiin ja muihin tilanteisiin, joissa “täydellinen satunnaisuus” on tavoite.


UUID v7: aikajärjestyksessä etenevä evoluutio

UUID v7 standardoitiin vuonna 2024 (RFC 9562). Sen ensimmäiset 48 bittiä ovat UNIX-epookkia millisekunneissa, loppu täytetään satunnaisuudella. Lexikografinen järjestys (merkkijonovertailu) vastaa tällöin luontijärjestystä, joten v7 toimii erinomaisesti pääavaimena – indeksin paikallisuus säilyy. Se mahtuu suoraan myös olemassa oleviin uuid-tyyppeihin tai BINARY(16)-sarakkeisiin.

  • Satunnaisuusbudjetti: version ja variantin hallintabittien jälkeen käytössä on noin 74 bittiä satunnaisuutta. Moni toteutus tekee lisäksi monotonisia säätöjä välttääkseen törmäyksiä saman millisekunnin sisällä; entropia riittää silti hyvin.
  • Tietovuoto: tunnisteesta voi päätellä luontiajan millisekunnin tarkkuudella. Jos satunnaisuus on heikkoa ja tunnisteita syntyy valtavasti, lähekkäisten arvojen arvaaminen helpottuu. Sisäisissä järjestelmissä tämä yleensä hyväksytään, mutta julkisissa päätepisteissä järjestyksen paljastuminen voi olla riski.

ULID: ihmisläheinen tunniste

ULID on vuodesta 2016 alkaen yleistynyt de facto -standardi. Esitysmuotona on 26 merkkiä pitkä Crockfordin Base32, josta on karsittu helposti sekoittuvat merkit (O/I/L/1), joten se sopii hyvin URL-osoitteisiin ja kopiointiin. Kuten v7, myös ULID:n ensimmäiset 48 bittiä ovat aikaleimaa (ms), joten lexikografinen järjestys vastaa aikajärjestystä.

  • Lajittelu: ULID-merkkijonot järjestyvät aina aikajärjestykseen, ja laajalti käytetty monotoninen generointi minimoi törmäyksiä.
  • Tallennusmuoto: TEXT(26) pitää esityksen luettavana, mutta binaarinen tallennus edellyttää Base32↔16 tavun muunnoksia. Moni relaatiotietokantojen UUID-tyyppi ei tue ULID-arvoja sellaisenaan.
  • Tietovuoto: aivan kuten v7, ULID paljastaa aikaleiman (ms). Jos et halua API-käyttäjien päättelevän jakelujärjestystä, harkitse vaihtoehtoja.

Vertailutaulukko (käytännön näkökulma)

Ominaisuus UUID v4 UUID v7 ULID
Standardointi RFC 4122 RFC 9562 (2024) De facto, ei standardia
Bittirakenne 128 bittiä joista 122 satunnaista 48-bit UNIX ms + loppu satunnaista (monotonia mahdollista) 48-bit UNIX ms + 80-bit satunnaista
Satunnaisuuden määrä ≈122 bittiä ≈74 bittiä (version/variantin jälkeen) 80 bittiä
Merkkimuoto 36 merkkiä (heksadesimaali + yhdysmerkit) 36 merkkiä (heksadesimaali + yhdysmerkit) 26 merkkiä (Crockford Base32)
Luonnollinen järjestys (teksti) ✗ (satunnainen) ✓ (lexikografinen = aikajärjestys) ✓ (lexikografinen = aikajärjestys)
Luonnollinen järjestys (binaari) ✓ (BINARY(16) nousee aikajärjestyksessä) ✓ (kun 6 tavun aikaleima on big-endian ennen satunnaisjaksoa)
Tietokantayhteensopivuus uuid / BINARY(16) ovat ihanteellisia uuid / BINARY(16) ovat ihanteellisia TEXT(26) säilyttää luettavuuden; BINARY(16) vaatii muunnoksen ja monen UUID-tyypin tuki puuttuu
Indeksin paikallisuus Heikko (satunnaislisäykset kuormittavat) Hyvä (lähes peräkkäiset lisäykset, kuitenkin hot spot -riski) Hyvä (sama huomio kuin v7:ssä)
Tasa-arvovertailun kustannus Matala (16 tavun vertailu) Matala (16 tavun vertailu) TEXT vertailu on raskaampaa; BINARY kevyt
Koodausrasite Heksadesimaali↔16 tavua (kevyt) Heksadesimaali↔16 tavua (kevyt) Base32↔16 tavua (raskaampi)
Luettavuus / URL-kelpoisuus Matala Matala Korkea
Tietovuoto Ei Aikaleima (ms) Aikaleima (ms)
Tyypilliset käyttökohteet Istuntotunnisteet, kertakäyttöiset avaimet Tietokantojen pääavaimet, tapahtumatunnisteet, lokien järjestys Julkiset tunnisteet ja lokit, joissa luettavuus auttaa

Kuuma-alueen varoitus v7:lle/ULID:lle: jos kaikki lisäykset osuvat yhdelle shardille tai johtajalle, peräkkäiset lisäykset voivat silti kuumentaa B-puun lehtiä. Etubittien kevyellä sekoituksella (“prefix shuffle”) tai yhdistämällä tunniste toiseen shardiavaimeen kuormaa voi tasata.


Tietokantatoteutusten muistiinpanot (PostgreSQL / MySQL / SQLite)

  • PostgreSQL
    • v4/v7: uuid-tyyppi on optimi. Kun tuot v7:n tekstinä ja castaat uuid:ksi, saat luonnollisen järjestyksen.
    • ULID: käytä char(26) / text -sarakeita tai bytea(16)-sarjoja Base32-muunnoksen jälkeen.
  • MySQL / InnoDB
    • BINARY(16) on kompakti ja nopea v4/v7:lle. v7 säilyy aikajärjestyksessä big-endian-muodossa. ULID sopii CHAR(26)-sarjoihin tai BINARY(16)-sarjoihin muunnoksen kanssa.
  • SQLite
    • Natiivia UUID-tyyppiä ei ole. Käytä BLOB(16)- tai TEXT-sarakkeita. Indeksoidut BLOBit toimivat riittävän hyvin.

Tietoturvanäkökulmia

  • Arvattavuus: v7 ja ULID jakavat samat aikaleimabitit. Jos luot runsaasti tunnisteita saman millisekunnin sisällä ja satunnaislähde on heikko, lähiarvojen ennustettavuus kasvaa. Käytä kryptografisesti turvallista PRNG:tä ja pidä monotoniset säädöt tasapainossa.
  • Metadatan vuoto: tunniste paljastaa luontiajan ja karkean jakaumavauhdin. Julkisissa API:ssa harkitse sisäisten ja ulkoisten tunnisteiden erottamista.

Yhteenveto: valintaperusteet

  • UUID v4: puhdas satunnaisuus. Ei järjestystä. Teoreettiset törmäykset ovat käytännössä olemattomia. Sopii istuntotunnisteisiin, CSRF-tokeneihin ja vastaaviin.
  • UUID v7: standardoitu järjestetty UUID. Erinomainen sisäisiin järjestelmiin ja tietokantojen pääavaimiksi. Monotoninen generointi tekee törmäyksistä käytännössä mahdottomia.
  • ULID: verrattain ihmisläheinen. Hyvä valinta URL-osoitteisiin ja lokien luettavuuteen, mutta sisäisenä pääavaimena v7 on usein mukavampi. Monotoninen generointi estää törmäyksiä käytännössä.

Liite: UUID v1 ja v6 (lyhyesti)

  • UUID v1 (aikapohjainen + MAC) 60 bitin aikaleima (100 ns) ja solmuidentiteetti (usein MAC-osoite). Tarjoaa vahvan aikajärjestyksen, mutta paljastaa potentiaalisesti hostin MAC-osoitteen ja vaatii huolellisen kellon takaisinkelausten käsittelyn. Yksityisyyssyistä sitä vältetään nykyisin usein.

  • UUID v6 (uudelleen järjestetty v1) Järjestelee v1:n aikaleiman big-endian-muotoon lajiteltavuuden parantamiseksi. Historiallisesti sitä ehdotettiin “lajiteltavaksi v1:ksi”, mutta standardointi on käytännössä kääntynyt v7:ään. Uusissa suunnitelmissa v7 on suositeltavampi kuin v6.


Toteutuksen tarkistuslista

  • Käytä kryptografisesti turvallista PRNG:tä satunnaisuuteen.
  • Kun käytät v7/ULID:n monotonista generointia, varmista ettei satunnaisuuden vinoutta synny samalla kun vältät saman millisekunnin törmäykset.
  • Suosi uuid / BINARY(16) -sarakkeita, jotta vältyt merkkijonosarakkeiden kollaatioiden kustannuksilta.
  • Päätä ulkoisen tunnistepolitiikan periaatteet (sallitaanko jakelujärjestyksen paljastuminen?). Erottele sisäiset ja ulkoiset tunnisteet tarvittaessa.

Johtopäätös: tämän päivän työkaluilla UUID v7 on oletusvalinta sisäisiksi pääavaimiksi, kun taas ULID on vahva, jos luettavuus tai perintöjärjestelmän vaatimukset painavat. v4 tai muut vaihtoehdot jäävät erityistapauksiin, joissa aikaleiman paljastuminen ei tule kyseeseen.