7 puan yazan GN⁺ 2024-11-13 | 2 yorum | WhatsApp'ta paylaş
  • Postgres’in resmi dokümantasyonu harika, ancak Postgres 17 PDF’i 3.200 sayfa olduğu için, yeni başlayanların gerçek işe geçmeden önce şema tasarımını, SQL davranışlarını ve operasyonel tuzakları yalnızca dokümanlardan öğrenmesi zor
  • Özel bir neden yoksa veriyi normalize edin; okuma performansı için yinelenen veri tutan denormalizasyon ise tutarsızlık ve yazma karmaşıklığı maliyetini beraberinde getirir
  • SQL anahtar kelimeleri büyük/küçük harfe duyarlı değildir, ancak NULL “bilinmiyor” kavramına daha yakındır; bu yüzden genel dillerdeki null gibi karşılaştırırsanız beklenmedik sonuçlar alabilirsiniz
  • psql içinde pager, \x, .psqlrc, \pset null, otomatik tamamlama, ters eğik çizgi komutları ve \copyyi iyi kullanmak bile çıktı okunabilirliğini, keşfi ve CSV dışa aktarmayı büyük ölçüde kolaylaştırır
  • İndeksler, kilitler, transaction’lar ve JSONB güçlüdür; ancak sorgu planlarını ve operasyonel kısıtları bilmezseniz performans düşüşüne veya erişilebilirlik sorunlarına yol açabilir

Devasa resmi dokümantasyondan önce bilinmesi gereken bağlam

  • Postgres resmi dokümantasyonu, mevcut sürüm 17 için US letter PDF olarak yazdırıldığında 3.200 sayfa, A4 olarak yazdırıldığında ise 3.024 sayfadır
  • Postgres kullanmadan önce bilinmesi iyi olacak çok sayıda pratik bilgi vardır; bunların bir kısmı diğer SQL DBMS’ler için de geçerli olabilir, ancak geçerlilik kapsamı her zaman net değildir

Veriyi varsayılan olarak normalize edin

  • Normalizasyon, veritabanı şemasında yinelenen veya gereksiz veriyi kaldırma sürecidir
  • documents tablosunda user_emaili doğrudan saklarsanız, kullanıcı e-postasını değiştirdiğinde o kullanıcıya ait tüm belge satırlarını güncellemeniz gerekir
    • Bunun yerine documents içindeki her satırın users gibi başka bir tablodaki satırı user_id yabancı anahtarıyla referans almasını sağlayabilirsiniz
  • “1st normal form” gibi tüm normal formları ezberlemeniz gerekmez, ancak genel normalizasyon süreci genellikle bakımı daha kolay şemalara yol açar
  • Denormalizasyon, belirli verileri her seferinde yeniden hesaplamadan hızlı okumak için yinelenen veri tutma yöntemidir
    • Çalışan vardiya uygulamasında, bu yılın birikmiş toplam çalışma süresini her seferinde tüm shift duration değerlerini toplayarak hesaplamak yerine, periyodik olarak veya çalışma süresi değiştiğinde hesaplayıp saklayabilirsiniz
    • Bu veri Postgres içinde tutulabileceği gibi Redis gibi bir cache katmanında da tutulabilir
  • Denormalizasyonun neredeyse her zaman bir maliyeti vardır; bunun en tipik maliyetleri veri tutarsızlığı olasılığı ve artan yazma karmaşıklığıdır

Postgres projesinin “bunu yapmayın” tavsiyeleri

  • Resmi Postgres wiki’sinde “Don’t do this” listesi bulunur
  • Tüm maddeleri anlamıyor olmanız sorun değildir; anlamadığınız maddelerde aynı hatayı yapma olasılığınız da düşüktür
  • Özellikle şu tavsiyeleri akılda tutmaya değer

SQL’de kafa karıştırması kolay davranışlar

  • SQL anahtar kelimelerinin büyük harf olması gerekmez

    • SQL anahtar kelimeleri büyük/küçük harfe duyarlı değildir
    • Aşağıdaki sorgular aynı anlama gelir
    SELECT * FROM my_table WHERE x = 1 AND y > 2 LIMIT 10;
    select * from my_table where x = 1 and y > 2 limit 10;
    SELECT * from my_table WHERE x = 1 and y > 2 LIMIT 10;
    
    • Bu özellik yalnızca Postgres’e özgü değildir
  • NULL, genel dillerdeki null/nil ile aynı değildir

    • SQL’deki NULL, genel programlama dillerindeki null ya da nilden çok “bilinmiyor” kavramına yakındır
    • NULL = NULL, true değil NULL döndürür
    • Taraflardan biri NULL olan karşılaştırmalarda sonuç çoğunlukla yine NULL olur
    • NULL karşılaştırmaları için şu işlemleri kullanmanız gerekir
      • x IS NULL: x, NULL ise true
      • x IS NOT NULL: x, NULL değilse true
      • x IS NOT DISTINCT FROM y: x = yye benzer ama NULLü normal bir değer gibi ele alır
      • x IS DISTINCT FROM y: x != y/x <> yye benzer ama NULLü normal bir değer gibi ele alır
    • WHERE bölümü yalnızca koşul true olduğunda satır döndürür
      • SELECT * FROM users WHERE title != 'manager', title değeri NULL olan satırları döndürmez
      • Çünkü NULL != 'manager' sonucunun değeri NULLdür
    • COALESCE, birden çok argüman içinden NULL olmayan ilk değeri döndürür
    COALESCE(NULL, 5, 10) = 5
    COALESCE(2, NULL, 9) = 2
    COALESCE(NULL, NULL) IS NULL
    

psqli daha kullanışlı hale getirmek

  • Çıktı okunabilirliğini iyileştirme

    • Çok sütunlu veya uzun değerli tabloları sorguladığınızda çıktı okunması zorsa pager kapalı olabilir
    • Terminal pager, büyük metinleri veya psql tablolarını görünüm alanı içinde kaydırarak incelemenizi sağlar
    • Çok sütunlu tablolar için \pset expanded veya \x ile expanded mode açabilirsiniz
    • Varsayılan olarak kullanmak isterseniz home dizininizdeki ~/.psqlrc dosyasına \x ekleyebilirsiniz
  • NULL çıktısını daha belirgin hale getirme

    • Varsayılan ayar, çıktı içinde NULL olup olmadığını net biçimde göstermez
    • psql içinde NULL gösterim dizesini belirleyebilirsiniz
    \pset null '[NULL]'
    
    • Unicode dizeler de kullanılabilir; bunu varsayılan yapmak için aynı komutu ~/.psqlrc içine ekleyebilirsiniz
  • Otomatik tamamlama ve ters eğik çizgi komutlarını kullanma

    • psql, etkileşimli bir konsol gibi otomatik tamamlama destekler
    • Bir anahtar kelimenin veya tablo adının bir kısmını yazıp Tab’a bastığınızda geri kalanını tamamlayabilirsiniz
    • Faydalı ters eğik çizgi komutları şunlardır
      • \?: tüm kısayolların listesi
      • \d: relation, yani tablo ve sequence listesi ile sahiplerini gösterir
      • \d+: \dye boyut ve bazı metadata bilgileri ekler
      • \d table_name: tablo şeması, sütun tipleri, nullable durumu, varsayılan değerler, indeksler ve yabancı anahtar kısıtlarını gösterir
      • \e: sorguyu, $EDITOR ortam değişkeninde ayarlı varsayılan editörde düzenler
      • \h SQL_KEYWORD: ilgili SQL anahtar kelimesinin sözdizimini ve dokümantasyon bağlantısını gösterir
  • CSV dışa aktarma ve SELECT takma adları

    • \copy ile sorgu sonuçlarını CSV olarak kaydedebilirsiniz
    \copy (select * from some_table) to 'my_file.csv' CSV
    
    • Sütun adlarını ilk satıra eklemek için HEADER seçeneğini kullanın
    \copy (select * from some_table) to 'my_file.csv' CSV HEADER
    
    • \copy, daha standart olan COPY ifadesinin gerektirdiği yükseltilmiş ayrıcalıklardan kaçınmanızı sağlar
    • SELECT çıktı sütunlarına AS ile takma ad verebilirsiniz
    SELECT vendor, COUNT(*) AS number_of_backpacks
    FROM backpacks
    GROUP BY vendor
    ORDER BY number_of_backpacks DESC;
    
    • GROUP BY ve ORDER BY içinde, SELECTten sonra gelen sütun numaralarına referans verebilirsiniz
    SELECT vendor, COUNT(*) AS number_of_backpacks
    FROM backpacks
    GROUP BY 1
    ORDER BY 2 DESC;
    
    • Bu kısaltma yararlıdır, ancak production’a dağıtılan sorgularda kullanmamak daha iyidir

İndeksler eklendiğinde her zaman kullanılmaz

  • İndeksler ve sorgu planları

    • İndeks, tablo satırlarını belirli alanlara göre bulmak için kullanılan bir veri yapısıdır; bir kısayol dizini gibi çalışır
    • En yaygın indeks türü B-tree’dir ve WHERE a = 3 gibi tam eşitlik koşullarında veya WHERE a > 5 gibi aralık koşullarında çalışır
    • Postgres’e belirli bir indeksi kullanmasını doğrudan söyleyemezsiniz
    • Postgres, her tablo için tuttuğu istatistiklere dayanarak bir indeksin, tabloyu baştan sona okuyan sequential scan’den daha hızlı olup olmayacağını tahmin eder
    • SELECT ... FROM ... ifadesinin başına EXPLAIN eklediğinizde, Postgres’in sorguyu nasıl çalıştıracağına dair sorgu planını görebilirsiniz
    • Sorgu planı okurken thoughtbot’un EXPLAIN ANALYZE rehberi, pganalyze dokümantasyonu, resmi dokümantasyon ve explain.depesz.com kaynaklarına bakabilirsiniz
  • Küçük tablolar ve çok sütunlu indeksler

    • Yerel geliştirme veritabanındaki gibi az satırlı tablolarda indeksler çok fayda sağlamayabilir
    • Örneğin 100 satır civarında bir tabloda Postgres, indeks yerine sequential scan’in daha hızlı olduğuna karar verebilir
    • Postgres, çok sütunlu indeksleri destekler
    CREATE INDEX CONCURRENTLY ON tbl (a, b);
    
    • WHERE a = 1 AND b = 2 gibi koşullar, a ve b üzerinde ayrı ayrı indeksler bulundurmaktan daha hızlı olabilir
    • Bunun nedeni, tek bir B-tree üzerinde gezinirken arama koşullarını verimli biçimde birleştirebilmesidir
    • (a, b) indeksi, yalnızca a ile filtreleyen sorguları da tek başına a indeksi kadar hızlı hale getirir
    • WHERE b = 5 gibi sorgular hızlanabilir, ancak en iyi çözüm olmayabilir
      • Çünkü indeks önce a, sonra b anahtarına göre sıralanmıştır; bu yüzden b değerini bulmak için tüm a değerleri boyunca ilerlenmesi gerekebilir
    • Birden fazla sütun kombinasyonuyla sorgu çalıştırmanız gerekiyorsa, çoğu zaman (a, b) ile birlikte yalnızca b için de ayrı bir indeks tutulur
    • İhtiyaca göre a ve b için ayrı tek sütunlu indekslere de güvenebilirsiniz
  • Prefix match için text_pattern_ops kullanın

    • Materialized path yöntemiyle hiyerarşik dizinler saklıyor ve belirli bir prefix ile başlayan tüm descendant kayıtlarını bulmanız gerekiyor olabilir
    SELECT * FROM directories WHERE path LIKE '/1/2/3/%'
    
    • path sütunu üzerinde varsayılan bir B-tree indeksi oluştursanız bile bu sorguda kullanılmayabilir
    CREATE INDEX CONCURRENTLY ON directories (path);
    
    • Prefix match veya pattern match için gereken karakter bazlı sıralamayı mümkün kılmak istiyorsanız operator class belirtmeniz gerekir
    CREATE INDEX CONCURRENTLY ON directories (path text_pattern_ops);
    

Kilitlerin ve transaction’ların yarattığı operasyonel sorunlar

  • Postgres’te kilitler

    • Kilit (lock) ya da mutex, riskli işlerin aynı anda yalnızca tek bir istemci tarafından yapılmasını sağlayan mekanizmadır
    • Veritabanında row, table, view gibi nesnelerin güncellenmesi ya tamamen başarılı olmalı ya da tamamen başarısız olmalıdır; eşzamanlı işlemler nedeniyle yalnızca bir kısmının başarılı olmasını önlemek için ilgili nesnelerde kilit alınır
    • Postgres’in tablo kilidi seviyeleri, daha az kısıtlayıcı olandan daha kısıtlayıcı olana doğru birkaç basamaktan oluşur
      • ACCESS SHARE: SELECT
      • ROW SHARE: SELECT ... FOR UPDATE
      • ROW EXCLUSIVE: UPDATE, DELETE, INSERT
      • SHARE UPDATE EXCLUSIVE: CREATE INDEX CONCURRENTLY
      • SHARE: CREATE INDEX, ancak CONCURRENTLY olmadan
      • ACCESS EXCLUSIVE: birçok ALTER TABLE, ALTER INDEX türü
    • Aynı tabloda şu işlemler mümkün olabilir ya da beklemek zorunda kalabilir
      • UPDATE sırasında SELECT: mümkün
      • UPDATE sırasında CREATE INDEX CONCURRENTLY: mümkün
      • SELECT sırasında CREATE INDEX: mümkün
      • SELECT sırasında ALTER TABLE: genellikle bekler
      • ALTER TABLE sırasında SELECT: genellikle bekler
    • Bazı ALTER TABLE türleri daha zayıf kilitler gerektirebilir; tüm bilgiler için resmi explicit locking dokümantasyonuna ve işlem türüne göre kilit çakışması rehberine bakabilirsiniz
  • Yavaş ALTER TABLE ve kilit kuyruğu

    • ALTER TABLE uzun sürerse, aynı tabloyu okuyan SELECT sorguları da bloke olabilir
    • Bu tablo bir web uygulamasındaki tüm isteklerin referans verdiği users gibi kritik bir tabloysa, istekler bekleyip timeout olabilir ve 503 döndürebilir
    • Yavaş ALTER TABLE işlemlerinin yaygın nedenleri şunlardır
      • sabit olmayan bir default değere sahip sütun eklemek
      • sütun tipini değiştirmek
      • uniqueness constraint eklemek
    • Postgres 11’den sonra, sütun eklerken tüm default değerlerin işlemi yavaşlatması sorunu düzeltildi; sorun çıkarabilecek olan sabit olmayan default’lardır
    • ALTER TABLE işleminin kendisi hızlı olsa bile, kilidi alana kadar çalışmaz
      • Uzun zamandır var olan bir dahili dashboard üzerindeki yavaş bir SELECT hâlâ çalışıyorsa ALTER TABLE beklemek zorunda kalabilir
    • Postgres kilitleri bir kuyruk oluşturduğu için, bekleyen bir ALTER TABLEın arkasına gelen aynı tablodaki sonraki sorgular da bekleyebilir
    • Aynı senaryo Migrations and exclusive locks yazısında daha ayrıntılı inceleniyor
  • Uzun transaction’lar da tehlikelidir

    • Transaction, birden fazla veritabanı ifadesini hep-ya-hiç mantığıyla bir araya getirir; BEGIN ile başlar ve COMMIT ile biter
    • Transaction içindeki değişiklikler diğer istemcilere görünmez; COMMIT olduğunda veritabanında görünür hale gelir
    • Para transferi gibi bir hesaptan bakiyenin düşmesi ve başka bir hesaba eklenmesinin birlikte başarılı olması ya da birlikte iptal edilmesi gereken işlemler için uygundur
    • Bir transaction kilit aldıysa, COMMITe kadar o kilidi elinde tutar
    • BEGIN sonrasında belirli bir row’u UPDATE edip masadan kalkarsanız, başka bir istemcinin aynı row üzerindeki DELETE işlemi transaction commit edilene kadar durur
    • Gerekenden uzun süre açık kalan transaction’lar, diğer istemcilerin sorgularını veya güncellemelerini engelleyebilir

JSONB keskin bir araçtır

  • JSONB’nin performans ve şema sorunları

    • JSONB esnektir, ancak yanlış kullanıldığında dezavantajları büyüktür
    • Postgres, JSONB sütunlarının istatistiklerini takip etmez; bu yüzden tek bir JSONB sütunu üzerindeki eşitlik sorguları, normal sütunlar kümesi üzerindeki sorgulardan çok daha yavaş olabilir
    • Bir örnekte JSONB yüzünden 2000 kat yavaşlama görülebilir
    • JSONB sütununa fiilen her şey konabilir; bu onu güçlü yapar ama yapıya dair güvenceleri azaltır
    • Normal tablolar için şemaya bakarak sorgu sonucunu tahmin edebilirsiniz; ancak JSONB’de key adının camelCase mi snake_case mi olduğu ya da bir durum alanının boolean mı enum mu olduğu net olmayabilir
    • Normal Postgres verisinin sahip olduğu statik tip özellikleri JSONB için aynı şekilde geçerli değildir
  • JSONB tip karşılaştırmalarının tuhaflığı

    • backpacks tablosundaki JSONB data sütununda brand alanı JanSport olan satırları bulmak istediğinizde şu sorgu çalışmaz
    select * from backpacks where data['brand'] = 'JanSport';
    
    • Postgres, karşılaştırmanın sağ tarafındaki tipin sol tarafla eşleşmesini bekler; sağ taraf da geçerli bir JSON dokümanı olmalıdır
    • JSON dokümanı; nesne, dizi, string, sayı, boolean veya null olmalıdır, bu nedenle tek başına JanSport geçerli JSON değildir
    • Doğru sorgu, ya JSON string ile karşılaştırmak ya da sol tarafı Postgres text tipine dönüştürmek şeklindedir
    select * from backpacks where data['brand'] = '"JanSport"';
    
    select * from backpacks where data['brand'] = '"JanSport"'::jsonb;
    
    select * from backpacks where data->>'brand' = 'JanSport';
    
    • SQL’deki NULL ile JSONB’deki null farklı çalışır
      • 'null'::jsonb = 'null'::jsonb, true döndürürken NULL = NULL sonucu NULLdür
    • JSONB için çok sayıda özel operatör ve fonksiyon vardır; bunları bir seferde akılda tutmak zordur
    • Postgres’te JSON değerlerini metin olarak saklayan JSON ile bunları verimli bir ikili biçime dönüştüren JSONB birlikte bulunur
    • JSONB’nin indekslenebilme gibi avantajları vardır; JSON formatı ise daha özel durumlara yönelik düşünülebilir

2 yorum

 
bbulbum 2024-11-19

Yapılmaması gerekenler; bir gün mutlaka okuyacağım.

 
GN⁺ 2024-11-13
Hacker News yorumları
  • PostgreSQL genel olarak büyük/küçük harfe duyarlıdır, ama SQL anahtar sözcüklerini büyük harfle yazmak çoğunlukla görsel örüntü eşleştirme yoluyla okunabilirliği artırma çabasıdır
    Şart değil, ama başkasının sorgusunu debug etmem gerekse, küçük sözdizimi biçimlerine takılmadan tanımı hızlıca gözden geçirmek için bir prettifier’a atardım
    Diğer dillerde kod biçimlendirmede olduğu gibi, tutarlı girintileme gibi görsel yapı da bariz kısımları anlamaya harcanan zamanı azaltır ve önemli olana odaklanmayı sağlar
    Ancak actuallyUsingCaseInIdentifiers gibi tanımlayıcılarda gerçekten büyük/küçük harf karıştırılmasından hiç hoşlanmıyorum; CLI’da kontrol etmek için çift tırnak gerektiren sütunlar görmek istemem

    • Büyük harfli tanımlayıcılar birbirinin yerine takılabilecek bloklar gibi görünüyor; küçük harfin sahip olduğu kelime biçimine kıyasla okuma hızını düşürüyor
    • SQL’i etkileşimli olarak kullanırken bu ayrımı bilmek epey işe yarıyor
      Kimsenin görmeyeceği geçici bir sorguyu hızlıca yazıp atacak olsam büyük/küçük harfi umursamam, ama depoya commit edilecek SQL’de komutları ALL CAPS yazarım
    • Büyük harfin siyah-beyaz ekranlarda sözdizimi vurgulama işlevi gördüğünü düşünüyorum
      Renkli ekranların olduğu günümüzde artık gerekli değil, ama bu eski bir hatıra; elimde kaynak yok
    • PostgreSQL tanımlayıcıları küçük harfe indirgerken standart büyük harfe indirger; bu yüzden büyük/küçük harf işleme konusunda standardı ihlal eder
      Yine de tırnak içindeki ve tırnaksız tanımlayıcıları karıştırmamak gerekir; iç yapıyı sorgulama da çoğunlukla standartlaşmış değildir, bu yüzden bunun pek önemi yok
    • SQL için prettifier veya linter önerileri merak ediyorum
  • PostgreSQL wiki’sindeki “don’t do this” maddesini ilk kez gördüm ve oldukça faydalı: https://wiki.postgresql.org/wiki/Don%27t_Do_This

    • Bu özellikler bu kadar kolay tuzaklara dönüşüyorsa neden kullanımdan kaldırılacak şekilde işaretlenmediklerini merak ediyorum
      Örneğin yeni şemalarda tablo kalıtımı gibi özellikleri devre dışı bırakıp, tekrar açmak için kasıtlı olarak karmaşık bir ayar gerektirmek daha doğru görünüyor
    • SQL Anti-patterns aklıma geliyor; veritabanlarıyla uğraşan herkesin okuması gereken bir kitap olduğunu düşünüyorum
    • MySQL tarafında edindiğim bazı alışkanlıkları yeniden düşünmeme neden oldu
  • Burada geçen şeylerin çoğu yalnızca PostgreSQL’e özgü değil
    NULL’un tuhaf davranışı, indeks sütun sırası gibi şeyler buna dahil; özellikle NULL ile indeks/unique kısıtlarının etkileşimi MySQL’de de sezgisel değil
    Örneğin email alanı NULL olamaz, username alanı NULL olabilir olan bir kullanıcı tablosunda (email, username) unique kısıtı koyarsanız, username değeri NULL olan aynı email birden fazla kez eklenebilir. Çünkü NULL, başka bir NULL’a eşit değildir

    • Not olarak, PostgreSQL 15’ten itibaren kısıtlarda ve unique indekslerde NULLS [NOT] DISTINCT ile bu davranışı etkileyebilirsiniz
      https://www.postgresql.org/docs/devel/sql-createtable.html#S...
    • Bu varsayılanın pratik açıdan gayet makul olduğunu düşünüyorum
      Ters davranışın gerektiği kullanım senaryoları çok daha nadir
  • “İyi bir neden yoksa verileri normalize edin” deyip geçmek sorunlu
    Yazarın bağlantı verdiği sayfada, normal olmayan form dahil normal formlar 11 tane olarak geçiyor; çoğu kişi bunların ne olduğunu bile bilmez ve bunlardan 7’sini zaten kullanmaz
    İnsanları daha yüksek normal form arayışına sürüklememek gerekir

    • Yine de yazar genel olarak ne demek istediğini açıklayan bir paragraf eklemiş ve bu yönü doğru buluyorum
      Yakın zamanda geçtiğim projede de bu tür birkaç sorunu düzeltmem gerekti; veriyi çoğaltmak için neredeyse hiç neden yok
    • Bu yazı yeni başlayanları hedefliyorsa, emin olunmadığında cevap neredeyse her zaman Üçüncü Normal Formdur
    • Genel kural, mümkün olduğunca normalize edip ardından gereken performans elde edilene kadar denormalize etmektir
  • İlk ipucu her gün VACUUM çalıştırmak
    Başlarken bunu bilmiyordum; reddit veritabanında hiç VACUUM yapmadım ve bir gün mecburen çalıştırdığımda, bitmesini beklerken reddit neredeyse bir gün boyunca kapalı kaldı

    • autovacuum yokmuş gibi görünüyor
      reddit ölçeğinde transaction ID’lerin önce tükenmemiş olması şaşırtıcı
  • Geliştiricilerin normalizasyona daha fazla önem vermesini ve her şeyi JSONB sütunlarına tıkıştırmayı bırakmasını isterdim

    • Veritabanları yapılandırılmış JSON saklayabilir hale gelmeden çok önce bile junior geliştiriciler, uygun normalizasyon düzeyi üzerine hararetli ama teorik tartışmalar yapardı
      Daha deneyimli geliştiriciler, doğru yanıtın anahtarlar dışında hiçbir şeyi yinelememek ve denormalizasyona ancak gerçekten istemeye istemeye başvurmak olduğunu bilirdi
      Sonra Mongo gibi veritabanları ortaya çıkıp, normalizasyonun zor ya da anlamsız olduğu “veritabanı benzeri şeyler” sunarak bu junior’ları cesaretlendirdi; bunun sonucunda korkunç veritabanı tasarımları ve bakımı imkânsız çöp kuleleri kısa süreliğine serpilip gelişti
      Şimdi sarkaç geri döndü ve normalize veritabanlarının avantajları yeniden keşfedildi, ancak JSON sütunları hâlâ kötü pratiklerin büyüyebileceği bir kaçış yolu olmaya devam ediyor
    • JSONB sütun kullanmanın iki nedeni var
      Birincisi, JSON saklamak. Bir web sunucusu üçüncü taraf bir API’yi çağırdığında ham API yanıtını bir JSONB sütununda saklayıp işlemi oradan yaparsa, o API’den kaynaklanan sorunları debug ederken denetlenebilir bir kayıt kalır
      İkincisi, sum type saklamak. SQL’in sum type desteklememesi, SQL veritabanlarında veri modellemenin en büyük kusurlarından biri sayılabilir
      Çeşitli geçici çözümler var ve “JSONB sütununa koyup uygulamada doğrula” da bunlardan biri; ama bu çözümlerin hiçbiri özellikle harika değil
    • Normalizasyona dikkat etseniz bile sonunda çoğu zaman ıvır zıvır JSONB çekmecesi oluşur
      JSONB içindeki değerleri ayrı sütunlara çıkarmadan, onun içinde kötü sorgular yazmıyorsanız, bunun başlı başına büyük bir sorun olduğunu düşünmüyorum
    • Bugün bu tür araçları kullanan geliştiricilerin çoğu aslında kendi veritabanı yönetim sistemini yapıyor ve kalıcılığı başka bir DBMS’e bırakıyor
      Çünkü kalıcılık gereksinimleri başarıyla karşılandığı sürece iyi tasarım üzerine düşünmeye yönelik güçlü bir baskı olmuyor
      Bir DBMS’in üstüne bir DBMS daha inşa etmek doğru mu, tartışılır; ama mevcut durum her hâlükârda bu
    • Bu yaklaşımın düzgün işlemesi için, şema değişikliklerini geri alabilme yeteneğini de içeren bir şema migrasyon süreci gerekir
      Yeni bir sütun performansı bozarsa ya da sorun çıkarırsa geri alınabilmeli
      İşin içinde CLI araçları varsa, ne kadar downtime’a katlanılabileceğini, şirket genelinde senkronize bir sürüm güncellemesinin mümkün olup olmadığını, yoksa bir süre hem eski hem yeni şemanın mı destekleneceğini de ele almak gerekir
      Veritabanı ekibin ana ürününün bir parçası değilse, tüm bunlar eksik olabilir
  • Yeni başlayanlara yardımcı olmak için bu yazıyı yazdım: https://tomcam.github.io/postgres/

  • Yazı gerçekten iyi ve PostgreSQL belgelerinin 3200 sayfa olduğunu bilmiyordum
    Bir süredir kullanıyorum ve ihtiyaç duydukça öğreniyorum; resmi belgeleri de epey seviyorum, belirli bir konu gerektiğinde ilgili yazıları okumayı da seviyorum
    Yazarın https://challahscript.com/what_i_wish_someone_told_me_about_... adresine (b, a) sütun indeksinin yalnızca b ile sorgularken iyi çalıştığını eklemesi okuyucuya yardımcı olur gibi
    a ile sorgulamadan bahsederken bu bir ölçüde ima ediliyor, ama daha açık yazmak fena olmaz
    JSON/JSONB kısmını pek kullanmadığım için çok bakmadım

  • Gerçek sahada gördüğüm gülünç SQL’leri düşününce, Codd makalesini okuyup ilişkisel modelin ne olduğunu anlamaya çalışmakla başlamak iyi olurdu
    Sadece 11 sayfa ve onu okumak bile dünyadaki acıyı azaltır

  • Bu yazının neredeyse tamamı MySQL gibi diğer MVCC veritabanları için de geçerli
    Ayrıntılar farklı olabilir, ama MySQL de uzun transaction’lardan muzdarip oluyor ve ALTER sırasında metadata lock alıyor; benzer eğlenceli sorunları var