21 puan yazan GN⁺ 2024-07-06 | 4 yorum | WhatsApp'ta paylaş
  • UUID, veritabanı tablolarında birincil anahtar olarak sıkça kullanılır
    • Üretmesi kolaydır, dağıtık sistemler arasında paylaşılması kolaydır ve benzersizliği garanti eder
    • UUID'nin boyutu düşünüldüğünde bunun doğru seçim olup olmadığı sorgulanabilir, ancak çoğu zaman buna biz karar veremeyiz
  • Bu yazı, "UUID anahtar için uygun bir format mı" sorusuna odaklanmak yerine PostgreSQL'de UUID'yi birincil anahtar olarak verimli biçimde nasıl kullanabileceğinizi anlatıyor

PostgreSQL'de birincil anahtar olarak UUID kullanmak

  • UUID nedir?
    • UUID, veritabanı tablolarında birincil anahtar olarak sıkça kullanılır
    • Dağıtık sistemler arasında kolayca paylaşılabilir ve benzersizliği garanti eder
    • Boyutu nedeniyle uygunluğu sorgulanabilir, ancak çoğu zaman başka seçenek yoktur

PostgreSQL'de UUID veri tipi

  • UUID'yi string olarak saklamak

    • PostgreSQL, string saklamak için text veri tipini sunar
    • Ancak text tipi, UUID saklamak için uygun değildir
    • PostgreSQL, UUID için özel uuid veri tipini sunar
    • uuid tipi 128 bitlik bir veri tipidir ve tek bir değeri saklamak için 16 bayt gerekir
    • text tipinde ek olarak 1 veya 4 baytlık overhead bulunur
  • Deney sonuçları

    • Karşılaştırma için iki tablo oluşturuldu: biri text tipi, diğeri uuid tipi
    • 10.000.000 satır eklendikten sonra tablo boyutu ve indeks boyutu karşılaştırıldı
    • text tipi kullanan tablo %54 daha büyük, indeks boyutu ise %85 daha büyüktü

UUID ve B-Tree indeksleri

  • B-Tree indeksleri ve UUID

    • Rastgele UUID'ler B-Tree indeksleri için uygun değildir
    • B-Tree indeksleri sıralı değerlerle iyi çalışır
    • Java'nın UUID.randomUUID() metodu UUID v4 döndürür; bu, sözde rastgele bir değerdir
    • UUID v7 zaman sırasına göre düzenlenmiş değerler üretir ve bu nedenle B-Tree indeksleri için daha uygundur
  • UUID v7 kullanımı

    • Java'da UUID v7 kullanmak için java-uuid-generator kütüphanesi gerekir
    • UUID v7 üretmek, ekleme performansını iyileştirebilir

UUID v7'nin INSERT performansına etkisi

  • Deney
    • UUID v7 kullanan bir tablo oluşturulup 10.000 satır 10 kez eklenerek performans ölçüldü
    • Sonuçlar biraz rastgele olsa da UUID v7 eklemek yaklaşık 2 kat daha hızlıydı

Ek okuma

  • PostgreSQL 17'de UUID v7'nin yerel olarak desteklenmesi mümkün olabilir
  • UUID v7 formatı hakkında bilgi
  • UUID'nin veritabanı birincil anahtarı olarak performansa etkisi

Özet

  • UUID uzunluğu sorunu

    • Optimizasyon yapılsa bile UUID, birincil anahtar için en ideal tip değildir
    • Seçenek varsa TSID gibi başka alternatifler değerlendirilmelidir
  • Optimizasyon ihtiyacı

    • Büyük veri kümeleri veya yüksek trafik bekleniyorsa optimizasyon düşünülmelidir
    • Birincil anahtarı değiştirmek zor bir iştir; bu yüzden baştan doğru kurmak önemlidir
  • Dikkat edilmesi gerekenler

    • Yazar bir PostgreSQL uzmanı olmadığını, sadece öğrendiklerini paylaştığını belirtiyor
    • Faydalı bulduysanız yorum veya Twitter üzerinden geri bildirim bekliyor

GN⁺ Özeti

  • Bu yazı, PostgreSQL'de UUID'yi birincil anahtar olarak kullanırken daha verimli yöntemleri ele alıyor
  • Deneyler, UUID v7 kullanmanın ekleme performansını artırabileceğini gösteriyor
  • Büyük veri kümeleri veya yüksek trafik beklenen durumlarda optimizasyon gerekli olabilir
  • TSID gibi başka seçenekler de değerlendirmeye değer

4 yorum

 
savvykang 2024-07-09

UUID için standart biçim (onaltılık + tireler) yerine base62 kodlaması istemek fazla mı olur?

 
qurare 2024-07-08

uuidv7 yenilmezdir
uuidv8+ ise "tanrı"dır

 
bbulbum 2024-07-08

En büyük engel, insan dostu olmaması.. Benim için hâlâ birçok noktada bu kısım gerekiyor..

 
GN⁺ 2024-07-06
Hacker News görüşü
  • B-tree dostu birincil anahtar olarak bigserial kullanılmasını ve harici kayıt konumlandırıcı seçeneği olarak dizeye kodlanmış UUID düşünülmesini öneriyor

    • Teknik olmayan kullanıcıların alıntı yapacağı durumlarda önce PNR tarzı konumlandırıcılar gibi daha basit seçenekleri değerlendirin
    • Servis veya uygulamanın şeması içinde PK türlerini karıştırmayın
    • Benzersiz tanımlayıcı olarak UUIDv7 kullanacaksanız, bunu yalnızca zaman kodu içeren verilere uygulayın
    • hashids kullanmayın; kriptografik kalitesi yoktur ve sıradan kullanıcılara da tanıdık gelmez
    • Kodlamada base64 veya tire içeren alfabeler kullanmayın
  • Veritabanı şeması tasarlarken ilgi alanlarının ayrılması ve mekanik sempatinin ilkelerini akılda tutun

  • Stripe’ın tiplenmiş rastgele ID’leri aslında rastgele değil

    • Metadata, gömülü zaman damgaları, shard ve referans anahtarları, sürüm bilgileri vb. içeriyor
    • Kişisel olarak base58 ile kodlanmış AES şifreli bigserial+HMAC konumlandırıcıları tercih ediyorum
  • Postgres’te rastgele UUID büyük bir sorun değil

    • UUID (16 bayt), serial (4 bayt) veya bigserial (8 bayt) değerlerinden daha büyüktür, ancak tüm tablo düzeyinde bu büyük bir mesele değildir
  • Postgres’te serial vs. rastgele UUID vs. sıralı UUID konusunu düşünmeden önce endişelenmeniz gereken çok daha fazla şey var

  • Yakın zamanda Postgres PK’si olarak ULID seçtim ve bu makaleden çok faydalandım: https://brandur.org/nanoglyphs/026-ids

  • ULID’yi tercih etmemin nedeni UUID türüyle uyumlu olması ve gömülü bir zaman damgası içermesi; bu sayede ID’ye göre sıralandığında zaman damgası sırasına göre de sıralanıyor

  • Karşılaştırmaya int64 da dahil edilse, UUID ile geleneksel yaklaşımın ek yükünü kıyaslamak iyi olurdu

  • Ekleme performansı, performansı değerlendirmek için kötü bir yöntemdir

    • B-Tree ekleme sırasında daha iyi performans gösterir, ancak büyük ölçekli işlemlerde durumun ne olacağı belirsizdir
  • SQLite’ta UUID4’ün tercih edilme nedeni, işlem kilidi sırasında sayfa önbelleği çakışması olasılığının daha düşük olmasıdır

    • Benzer şekilde Postgres sistemleri için de geçerli olabilir
  • Tamsayı otomatik artan birincil anahtarları tercih ediyorum

    • Anlaması kolay ve sıralaması basit
    • Büyük toplu iş projelerinde son birincil anahtarı kaydedip ondan büyük olan her şeyi çekebilirsiniz
  • UUIDv7 ekleme zamanı benchmark’ı UUID oluşturma süresini de içeriyor

    • Sadece indeks güncelleme maliyetinin ayrı olarak görülmesini isterdim
  • PostgreSQL 17’de UUIDv7 desteğinin yer alma olasılığı düşük

    • Yakın zamanda ilgili işten bir committer çıkarıldı ve 17 sürümü zaten özellik dondurma aşamasında
  • python-ulid kullanmaya başladım ve ULID’nin UUID’den daha üstün olduğunu düşünüyorum

  • UUID v7 standardı bağlantısı eski kaldığı için RFC 9562’ye bakın: https://datatracker.ietf.org/doc/html/rfc9562