En nefret ettiğimiz PostgreSQL kısmı (2023)
(cs.cmu.edu)- PostgreSQL son dönemde internetin varsayılan tercihi gibi öne çıktı, ancak Carnegie Mellon ve OtterTune deneyimine göre MVCC uygulaması MySQL, Oracle ve Microsoft SQL Server'a kıyasla daha fazla operasyonel yük getiriyor
- Satır güncellenirken mevcut satırın üzerine yazmak yerine yeni bir fiziksel sürüm oluşturan append-only depolama yaklaşımı ve eski sürümden yeni sürüme ilerleyen O2N zinciri temel tasarım unsuru
- Bu yapı tüm tuple'ın kopyalanmasına, dead tuple birikimine, tüm indekslerin güncellenmesine ve autovacuum bağımlılığına yol açıyor; yalnızca HOT update mümkün olduğunda bazı maliyetlerden kaçınılabiliyor
- OtterTune müşterilerinin PostgreSQL analizinde güncellemelerin ortalama yalnızca yaklaşık %46'sı HOT optimizasyonunu kullandı ve varsayılan autovacuum ayarları büyük tablolarda temizliği uzun süre geciktirebiliyor
- PostgreSQL hâlâ cazip bir DBMS, ancak yazma ağırlıklı iş yükleri ve büyük tablolarda depolama alanı, I/O, bellek, indeks bakımı ve vacuum operasyonunu doğrudan yönetmek gerekiyor
PostgreSQL MVCC neden sorun oluyor?
- Veritabanı seçenekleri çok fazla; Nisan 2023 itibarıyla DBDB'de 897 kayıtlı sistem bulunuyor, ancak dönemlere göre fiili varsayılan tercihler vardı
- 2000'lerde Google ve Facebook'un kullandığı MySQL alışıldık seçenekti
- 2010'larda MongoDB, “webscale” imajıyla öne çıktı
- Son 5 yılda PostgreSQL; kararlılığı, zengin özellik seti, genişletilebilirliği ve operasyonel iş yüklerine uygunluğu nedeniyle yaygın biçimde tercih edildi
- Yazının odağı PostgreSQL'in çok sürümlü eşzamanlılık denetimi (MVCC) uygulaması
- Carnegie Mellon'un araştırması ve Amazon RDS PostgreSQL optimizasyon deneyimlerine göre PostgreSQL'in MVCC uygulaması MySQL, Oracle ve Microsoft SQL Server'dan daha kötü değerlendiriliyor
- Amazon Aurora PostgreSQL de aynı yapısal sorunlara sahip
MVCC'nin amacı ve PostgreSQL'in tasarım tercihi
- MVCC, mümkün olduğunda birden fazla sorgunun birbirini engellemeden aynı anda veritabanını okuyup yazabilmesini sağlama yöntemi
- DBMS, mevcut satırın üzerine yazmak yerine her mantıksal satır için birden fazla fiziksel sürüm tutar
- Sorgular, oluşturulma zamanı gibi sürüm sırasına göre kendilerine uygun sürümü okur
- İşlem başlangıcındaki veritabanı anlık görüntüsünü görmeyi sağlayan snapshot isolation mümkün olur
- Okuma işlemleri, aynı öğeyi güncelleyen yazma işlemleri nedeniyle açık kayıt kilitleri tarafından engellenme durumunu azaltabilir
- MVCC kullanan bir DBMS'nin büyük ölçüde üç konuya karar vermesi gerekir
- Mevcut satır güncellemeleri nasıl saklanacak?
- Çalışma anında sorguya uygun satır sürümü nasıl bulunacak?
- Artık görünmeyen süresi dolmuş sürümler nasıl kaldırılacak?
- PostgreSQL, 1980'lerde yaptığı ilk tercih nedeniyle kalan iki alanda da bugün hâlâ yük taşıyor
append-only sürüm depolama
- PostgreSQL baştan itibaren çoklu sürüm desteğiyle tasarlandı; güncelleme sırasında mevcut satırın üzerine yazmak yerine bir kopya oluşturup değişiklikleri yeni sürüme uygular
- Bu yaklaşım append-only sürüm depolama olarak görülebilir
- Mevcut tuple güncellendiğinde DBMS tabloda yeni satır sürümü için boş bir slot bulur
- Geçerli sürümün satır içeriği yeni sürüme kopyalanır
- Değişiklikler yeni ayrılan sürüm slotuna uygulanır
- Örnek tablo, film bilgilerini tutan
moviestablosuidbirincil anahtardır;name,year,directorsütunlarına sahiptirmovies_pkeybirincil indeksi ileidx_nameveidx_directoryardımcı B+Tree indeksleri bulunur
"Shaolin and Wu Tang"filminin çıkış yılını 1985'ten 1983'e çeviren güncellemede önce özgün tuple kopyalanır, ardından değişen yıl yeni sürüme uygulanır- Mevcut sayfada yer yoksa yeni sürüm başka bir tablo sayfasında oluşturulabilir
Sürüm zinciri ve O2N yaklaşımı
- Birden fazla fiziksel sürüm aynı mantıksal satırı temsil ettiğinde DBMS'nin sürümler arası ilişkiyi kaydetmesi gerekir
- MVCC DBMS'leri, tek yönlü bağlı liste biçiminde sürüm zinciri oluşturur
- Zincir, depolama ve bakım maliyetini azaltmak için yalnızca tek yönde bağlanır
- Sürüm zinciri sıralamasının iki türü vardır
- N2O: en yeni sürüm önceki sürümü gösterir ve zincirin başı her zaman en yeni sürümdür
- O2N: her sürüm yeni sürümü gösterir ve zincirin başı en eski sürümdür
- Oracle ve MySQL dahil çoğu DBMS N2O kullanır
- PostgreSQL, Microsoft SQL Server'ın In-Memory OLTP motoru dışında nadiren görülen O2N yaklaşımını kullanır
- O2N, tuple her değiştiğinde indekslerin yeni sürümü işaret edecek şekilde güncellenme ihtiyacını azaltabilir
- Ancak en yeni sürümü bulmak için uzun sürüm zincirlerini takip etmek gerekebilir
- PostgreSQL satır başlığındaki
t_tcidalanı, bir sonraki sürümün tuple ID'sini tutar; en yeni sürümse kendi tuple ID'sini tutar- İndeks eski sürümü işaret ediyorsa PostgreSQL zinciri takip ederek yeni sürümü bulmak zorundadır
İndekslerle zincir taramasını azaltma yöntemi
- PostgreSQL geliştiricileri baştan beri iki maliyetin farkındaydı
- Her güncellemede tüm tuple için yeni bir kopya oluşturmanın maliyeti yüksektir
- Sorguların çoğunun istediği en yeni sürümü bulmak için tüm sürüm zincirini dolaşması israftır
- PostgreSQL, uzun zincir taramasını önlemek için satırın her fiziksel sürümü adına tablo indekslerine giriş ekler
- Tek bir mantıksal satırın 5 fiziksel sürümü varsa o tuple için indekslerde en fazla 5 giriş oluşabilir
idx_nameindeksi"Shaolin and Wu Tang"ın birden fazla sürümünü gösteriyorsa PostgreSQL en yeni sürüme doğrudan erişebilir
- En yeni sürüme erişim hızlanabilir, ancak indeksler büyür ve bakım maliyeti artar
HOT update optimizasyonu
- PostgreSQL, ilgili sürümlerin birden fazla sayfaya dağılması ve çok sayıda indeks girdisi oluşması durumunu azaltmak için HOT (heap-only tuple) update kullanır
- HOT update'in mümkün olması için iki koşul vardır
- Güncelleme, tablo indekslerinin referans verdiği sütunları değiştirmemelidir
- Yeni sürüm, önceki sürümle aynı veri sayfasında tutulabilecek kadar boş alan bulunmalıdır
- HOT uygulanırsa indeks eski sürümü göstermeye devam eder ve sorgu sürüm zincirini izleyerek en yeni sürümü bulur
- PostgreSQL, normal çalışma sırasında eski sürümleri kaldırarak sürüm zincirini budayan optimizasyonlar da yapar
dead tuple temizliği ve vacuum
- PostgreSQL her güncellemede satır kopyası oluşturduğu için eski sürümler olan dead tuple'ları temizlemek zorundadır
- 1980'lerdeki ilk PostgreSQL sürümleri dead tuple'ları kaldırmıyordu
- Eski sürümleri koruma fikri, veritabanının belirli bir andaki durumunu görmeye yarayan time-travel sorgularını mümkün kılmaktı
- Ancak dead tuple'lar silinmezse silme işlemleri olsa bile tablo boyutu küçülmez ve sık güncellenen tuple'ların sürüm zinciri uzar
- PostgreSQL, vacuum süreciyle tabloda dead tuple temizliği yapar
- Vacuum, son çalıştırmadan beri değişen tablo sayfalarını sıralı olarak tarar ve süresi dolmuş sürümleri bulur
- Bir sürüm etkin işlemler tarafından görünmüyorsa expired kabul edilir
- Mevcut işlem o sürüme erişmeyecek ve gelecekteki işlemler daha yeni live sürümü kullanacaksa alanı yeniden kullanmak güvenlidir
- PostgreSQL, yapılandırmaya bağlı olarak autovacuum'u periyodik olarak otomatik çalıştırabilir
- Genel ayarlarla tüm tablolar için vacuum sıklığı ayarlanabilir
- Tablo bazında autovacuum ayarı da yapılabilir
- Kullanıcılar
VACUUMSQL komutuyla bunu manuel olarak çalıştırabilir
Sorun 1: tüm tuple'ın kopyalanması
- append-only MVCC'de tuple'ın yalnızca tek bir sütunu değişse bile tüm sütunlar yeni sürüme kopyalanır
- Bu yaklaşım veri tekrarını ve depolama alanı ihtiyacını ciddi biçimde artırır
- PostgreSQL aynı veritabanını saklamak için diğer DBMS'lere göre daha fazla bellek ve disk gerektirebilir
- Sonuç olarak sorgular yavaşlayabilir ve bulut maliyetleri artabilir
- MySQL ve Oracle, yeni sürüm ile mevcut sürüm arasındaki sıkıştırılmış delta'yı saklar
- 1000 sütunlu bir tabloda yalnızca 1 sütun değişirse sadece değişen o sütun için delta kaydı tutulur
- PostgreSQL ise değişen 1 sütunla birlikte değişmeyen 999 sütunu da içeren yeni bir sürüm oluşturur
- PostgreSQL'in TOAST öznitelikleri farklı işlendiğinden bu karşılaştırmaya dahil edilmez
- EnterpriseDB, 2013'te append-only depolama motorunu delta sürüm tabanlı yapıya çevirmeyi amaçlayan zheap projesini başlattı
- Son resmi güncelleme 2021 tarihli durum yazısı oldu
- Sonrasında belirgin bir ilerleme görünmedi
Sorun 2: tablo bloat
- PostgreSQL'deki süresi dolmuş sürümler, yani dead tuple'lar, delta sürümlerden daha fazla alan kaplar
- Yazma ağırlıklı iş yüklerinde autovacuum yetişmeden dead tuple'lar daha hızlı birikebilir
- Tablolar sürekli büyüyebilir
- Dead tuple ve live tuple aynı sayfalarda karışık durduğundan sorgu yürütülürken dead tuple'ların da belleğe yüklenmesi gerekir
- Kontrolsüz bloat, tablo taramalarında daha fazla IOPS ve bellek tüketimine yol açarak sorgu performansını düşürür
- Dead tuple'lar nedeniyle optimizer istatistikleri yanlışlaşırsa kötü sorgu planları oluşabilir
- Örnek olarak
moviestablosunda 10 milyon live tuple ve 40 milyon dead tuple varsa verinin %80'i eski haldedir- Ortalama tuple boyutu 1KB ise live tuple'lar 10GB, dead tuple'lar yaklaşık 40GB yer kaplar
- Toplam tablo boyutu 50GB olur
- Tüm tablo taramasında PostgreSQL, çoğu eski veri olsa bile diskten 50GB okuyup belleğe almak zorundadır
- PostgreSQL'de sıralı taramanın buffer pool önbelleğini kirletmesini azaltan koruma mekanizmaları vardır, ancak bunlar I/O maliyetini ortadan kaldırmaz
VACUUM ile VACUUM FULL arasındaki fark
- autovacuum düzenli çalışıp iş yüküne yetişse bile normal autovacuum, depolama alanını işletim sistemine geri veremez
- Normal
VACUUM, dead tuple'ları kaldırır ve her sayfadaki live tuple'ları yeniden düzenler, ancak diskteki boş sayfaları geri kazanmaz - PostgreSQL son sayfayı boşaltabilirse o sayfayı kesebilir, fakat diğer sayfalar diskte kalır
- 50GB'lık tabloda 40GB dead tuple silinse bile PostgreSQL, işletim sistemi veya RDS açısından 50GB ayrılmış alanı koruyabilir
- Kullanılmayan alanı gerçekten geri vermek için
VACUUM FULLveya pg_repack ile tüm tabloyu yeni alana yeniden yazmak gerekir- Her iki işlem de çok kaynak tüketir ve uzun sürer
- Üretim veritabanlarında sorgu performansı üzerinde büyük etki yaratabilir
VACUUM FULL, her sayfadaki dead tuple'ları kaldırır, kalan live tuple'ları sıkıştırarak yeni sayfalara taşır ve gereksiz sayfaları siler
Sorun 3: yardımcı indeks bakımı
- PostgreSQL, tek bir tuple güncellenirken o tablodaki tüm indeksleri güncellemek zorundadır
- Çünkü hem birincil hem yardımcı indeksler sürümün tam fiziksel konumunu saklar
- Yeni sürüm öncekiyle aynı sayfaya yazılan bir HOT update değilse bu işlem her güncellemede gerekir
- Örnek güncellemede PostgreSQL yeni sürümü
Table Page #2üzerinde oluşturduktan sonramovies_pkey,idx_directorveidx_nameiçine yeni sürümü işaret eden girişler ekler - Tüm indeksleri değiştirmeyi gerektiren bu yapı çeşitli performans maliyetleri yaratır
- Update sorguları yavaşlar
- Her indeksin taranması ve yeni giriş eklenmesi için ek I/O oluşur
- İndeksler ve buffer pool page table gibi iç yapılarda lock/latch çekişmesi oluşur
- Gerçek sorguların kullanmadığı indeksler için bile bakım maliyeti ödenir
- Amazon Aurora gibi IOPS üzerinden ücretlenen DBMS'lerde ek okuma-yazma daha da sorunlu olur
- OtterTune müşterilerine ait PostgreSQL veritabanlarının analizinde güncellemelerin ortalama yaklaşık %46'sı HOT optimizasyonundan yararlanıyordu
- Kalan %50'den fazlası indeks bakım maliyetini taşıyordu
- Uber'in 2016 tarihli Postgres'ten MySQL'e geçiş yazısı bu sorunu gösteren tipik bir örnek
- Çok sayıda yardımcı indeksi olan tablolarda yazma ağırlıklı iş yükleri ciddi performans sorunları yaşadı
- Oracle ve MySQL'de yardımcı indeksler yeni sürümün fiziksel adresini tutmadığından aynı sorun yoktur
- Yardımcı indeksler tuple ID veya birincil anahtar gibi mantıksal tanımlayıcıları saklar
- DBMS bu mantıksal tanımlayıcıyla mevcut sürümün fiziksel adresini bulur
- Yardımcı indeks okumaları daha yavaş olabilir, ancak MVCC uygulamasının diğer avantajları bu ek yükü azaltır
Sorun 4: autovacuum operasyon zorluğu
- PostgreSQL performansı, eski verileri temizleyip alanın yeniden kullanılmasını sağlayan autovacuum'un etkinliğine büyük ölçüde bağlıdır
- RDS, Aurora ve Aurora Serverless dahil PostgreSQL türevlerinin hepsi aynı autovacuum sorunlarını taşır
- autovacuum karmaşıktır ve ideal durumda çalıştırılması zordur
- Varsayılan ayarlar her tablo için uygun değildir
- Özellikle büyük tablolarda sorun büyür
autovacuum_vacuum_scale_factoriçin varsayılan değer %20'dir- 100 milyon tuple'lık tabloda autovacuum'un tetiklenmesi için en az 20 milyon tuple'ın güncellenmiş olması gerekir
- Bu da çok sayıda dead tuple'ın uzun süre tabloda kalıp I/O ve bellek maliyeti yaratmasına yol açabilir
- long-running transaction autovacuum'u engelleyebilir
- Süresi dolmuş sürümlerin temizliği gecikirse dead tuple ve eski istatistikler birikir
- Performans sorunları daha fazla long-running transaction oluşturabilir ve bunlar da tekrar autovacuum'u engelleyerek kısır döngü yaratabilir
- Böyle durumlarda insanların long-running transaction'ı manuel olarak sonlandırması gerekebilir
OtterTune müşteri örnekleri
- Bir PostgreSQL Amazon RDS veritabanında dead tuple sayısı iki hafta boyunca testere dişi şeklinde değişti
- autovacuum günde yaklaşık bir kez büyük bir temizlik yapıyordu
- 14 Şubat'ta DBMS, 3,2 milyon dead tuple temizledi
- Ancak genel grafikte dead tuple sayısı artış eğilimindeydi; yani autovacuum'un yetişemediği sağlıksız bir durum vardı
- OtterTune müşterilerinden birinin PostgreSQL RDS örneğinde bulk insertion sonrasında eski istatistikler nedeniyle long-running query oluştu
- Bu sorgu, autovacuum'un istatistik güncellemesini engelledi
- Sonuç olarak daha fazla long-running query oluştu
- OtterTune'un otomatik health check sistemi sorunu tespit etti, ancak yöneticinin sorguyu manuel sonlandırması ve bulk insertion sonrasında ANALYZE çalıştırması gerekti
- İlgili uzun sorgunun çalışma süresi 52 dakikadan 34 saniyeye düştü
Pratik sonuç
- DBMS tasarımında her zaman zor tercihler vardır ve bu tercihler iş yüküne göre performansı değiştirir
- Uber'in belirli write-intensive iş yükünde, PostgreSQL MVCC'nin yarattığı indeks yazma amplifikasyonu MySQL'e geçiş nedenlerinden biriydi
- PostgreSQL'in MVCC uygulaması, bugün yeni bir MVCC DBMS yapılacak olsa izlenmemesi gereken bir yaklaşım olarak değerlendiriliyor
- Temel sorun append-only depolama ile autovacuum birleşimi
- Bu tasarım 1980'lerin mirası ve 1990'lardan sonra log-structured sistem desenleri yaygınlaşmadan önceki bir yaklaşım
- PostgreSQL hâlâ tercih edilen bir DBMS, ancak MVCC'nin zayıf yönleri kabul edilerek işletilmeli
- Geçici çözüm, ciddi miktarda zaman ve emek harcayarak sistemi elle tune etmektir
1 yorum
Hacker News yorumları
Postgres’in içini epey bildiğimi düşünmeme rağmen bu yazı mükemmeldi ve çok şey öğrendim.
Temel zayıflıklardan biri, Postgres’in satır sürümü takibinde N2O yerine O2N yaklaşımını seçmiş olması gibi görünüyor. N2O’ya geçmek tüm sorunları çözmezdi; örneğin satırın tüm kopyasını saklama sorunu kalırdı. Ama 80/20 açısından bakınca, mevcut uygulamanın dezavantajlarının çoğunu azaltabilirdi.
Çoğu transaction en güncel satır sürümünü isteyeceği için, N2O sırası kullanıldığında bağlı listeyi yalnızca eski sürüm gerektiğinde izlemek yeterli olurdu ve her satır sürümünü index’te saklamak gerekmeyebilirdi.
İlk dersin tamamını otele giremediği için Amsterdam sokaklarında yapıyor; karakteri de ilginç, iç işleyişi anlatma becerisi de muazzam.
Büyük avantajı, iş yükü çoğunlukla INSERT ve ardından tablo silmeden oluştuğunda ek alan gerektirmemesi.
Genelde insert transaction’larını bölmek de gerekmez. Çünkü üretilen veri boyutu veya değiştirilen toplam satır sayısı üzerinde pratik bir sınır yoktur. Transaction içindeki statement sayısında sınır var, ama tabloları çok sık değiştirmiyorsanız COPY FROM ile bunun etrafından dolaşılabilir.
DBA açısından rollback/undo alanını tablo depolamasından ayrı yönetmeye gerek yoktur. Uygulamaya göre değişir ama PostgreSQL tasarımı her açıdan kaybeden değil. Yani bubble sort gibi değil.
Liste neredeyse sıralı olduğunda performansı iyidir; 3D render’da nesneleri kameraya uzaklıklarına göre sıralamak buna bir örnektir. Kamerayı biraz hareket ettirdiğinizde veya döndürdüğünüzde, önceki frame’in sırasını temel alarak yeniden sıralamada bubble sort çok iyi çalışır.
En kötü durumlardan kaçınmak için son geçişte başarısız karşılaştırma sayısını ve o ana kadar yapılan geçiş sayısını sayıp, eşik aşılırsa başka bir sıralama algoritmasına geçmek yeterlidir.
30 yılı aşkın süredir eski bir teknoloji; bu yüzden her açıdan kaybeden olmasa bile, en önemli açılardan kaybeden olduğunu düşünüyorum.
Bence bu yazı özellikle şu bölümde hatalı:
“2000’lerde hâkim görüş, Google ve Facebook gibi yükselen teknoloji yıldızları MySQL kullandığı için MySQL’i seçti. 2010’larda ise dayanıklı olmayan yazmalar sayesinde ‘web ölçeğine’ çıkan MongoDB vardı. Son 5 yılda PostgreSQL internetin sevdiği DBMS oldu. Bunun iyi nedenleri var! Güvenilir, özellik açısından zengin, genişletilebilir ve çoğu operasyonel iş yüküne iyi uyuyor.”
Akıllı mühendislerin Postgres’i seçmesi popülerliğe başvurma safsatasından değil, veri güvenliği, ACID, Oracle’a benzerliği, MVCC, SQL standardına uyumu, Postgres ekibi, harika ve yardımsever topluluk, veri tipleri, yüksek performans ve BSD’nin esnekliği yüzündendi.
2000’lerin başında ATT’de Postgres’i seçme nedenleri de bunlardı ve Oracle DBA’leri de geçişi çok kolay benimsedi. MySQL zorlu bir dönüşümden geçerken PG güçlenmeye ve gelişmeye devam etti. Bruce Momjian’ın bu başarıda büyük rolü olduğunu düşünüyorum; gerçekten olağanüstü bir topluluğu var.
Eski bir AS400 veritabanı şeması ile modern bir Rails uygulaması arasında “canlı” bir uyumluluk katmanı oluşturmak için veritabanı view’larını kullanmak istiyordum.
Sonrasında veri güvenliği, transaction içinde DDL gibi şeyler sayesinde tercihim giderek güçlendi.
“MySQL ve Oracle, yeni sürüm ile mevcut sürüm arasındaki sıkıştırılmış deltayı saklar (git diff gibi düşünebilirsiniz).”
Git’in diff saklamadığı meşhurdur; burada Postgres’in kullandığı yöntem gibi yeni nesneyi ve önceki nesnenin tamamını saklamıyor mu?
Clone işlemini hızlandırmak için packing ile sıkıştırma yapar, ama Git’in ele aldığı ham biçim bu blob’lardır.
Git deposu da sıkıştırma yapar ve bu sıkıştırma bir tür diff tabanlıdır; ama safça bekleneceği gibi commit geçmişi tabanlı değildir.
SQL sorgularında da diff olduğu gibi döndürülmez.
“PostgreSQL’in her update için tablodaki tüm index’leri değiştirmek zorunda kalması, çeşitli performans etkileri doğurur. Doğal olarak sistemin daha fazla iş yapması gerektiği için update sorguları yavaşlar.”
Bu write amplification konusunu merak ediyordum. MySQL’in index’leri bu şekilde güncellemek zorunda olmadığı doğru, ama MySQL replikasyonu binlog’a dayanır ve her değişikliğin veritabanının kendisine (InnoDB redo log vb.) ek olarak ayrıca kaydedilmesi gerekir.
Bu yüzden cluster’da kullanılan MySQL’in başka türde bir write amplification’a sahip olduğu görülüyor. PostgreSQL replikasyon için WAL’ı yeniden kullandığından böyle bir amplification yok.
Üstelik alıcı tarafta MySQL gelen binlog’u önce relay log’a yazar; relay log’u applier thread tüketirken ek InnoDB yazmaları ve varsayılan ayarlarda ek binlog oluşturur.
Bu konu disk dışarıda bırakılarak tartışılamaz
SSD’ler tek seferde 4KB sayfa yazar. Yani yalnızca 1 bit güncellense bile disk 4KB okur, biti değiştirir ve 4KB sayfayı yeni bir slota yeniden yazar. Dolayısıyla kopyalamanın cezası disk türüne göre değişir
AWS, IO’nun MBps değeri için sabit ücret alıyor; en yakın 4KB’ye yuvarlama kuralı var mı, yoksa istek miktarını değil de sürücünün kendi yazma hacmini izleyip depolama implementasyonunda gerçekleşen gerçek IO miktarını mı ücretlendiriyor, bilmiyorum
“Oracle ve MySQL’in MVCC implementasyonunda bu sorun yok. Çünkü ikincil indeksler yeni sürümün fiziksel adresini saklamaz. Bunun yerine mantıksal bir tanımlayıcı (örn. tuple ID, birincil anahtar) saklar ve DBMS bunu kullanarak mevcut sürümün fiziksel adresini bulur. Bu yüzden ikincil indeks okumaları yavaşlayabilir; ancak bu DBMS’lerin MVCC implementasyonunda ek yükü azaltan başka avantajları vardır.”
MySQL’de gözlemlediğim ilginç bir davranış var. Yaklaşık 500GB’lık bir veritabanıydı ve şema ilişkisel olmaktan çok belge odaklıya yakındı;
SELECT id WHERE something; UPDATE what WHERE id=id,UPDATE what WHERE something’den birkaç mertebe daha hızlıydıBu davranışın nedeni muhtemelen burada olabilir diye düşünüyorum. Ancak normal iş yükü böyle yapmıyor; yalnızca tutarsızlıkları düzeltmek için kullanılan geçici DML’de yavaşlıyor
Buna karşılık UPDATE gerçekten yazma yapar ve tabloyu kilitleyebilir.
UPDATE id=id, satır düzeyi kilitlemeyi mümkün kılar. Ancak SELECT ile UPDATE arasında yeni eklenen kayıtları kaçırma riski de vardırToplu güncellemelerin çok yavaş olabileceğine katılıyorum. Sonunda güncellemeleri çoğu zaman partiler halinde kademeli işlemek ya da hatta COPY kullanmak gerekiyor
“2010’larda bu MongoDB’ydi. Dayanıksız yazmalar sayesinde ‘web scale’ olmuştu.”
Konu dışı ama baştan sona pazarlamaydı: https://news.ycombinator.com/item?id=15124306
4.2.8 sürümü (2020) epey sağlamlaşmıştı ve dirty write olmadığı biliniyor: https://en.wikipedia.org/wiki/MongoDB#Technical_criticisms
2024’te bile önüne hâlâ bağlantı havuzlayıcı (örn. pgbouncer) koymadan kullanılabilir hale gelmemesinden en çok nefret ediyorum
OrioleDB bu sorunu yeni bir depolama motoruyla çözmeye çalışmıştı: https://github.com/orioledb/orioledb
Oriole artık Supabase’e katıldı ve Alexander ile ekibi tam zamanlı olarak bunun üzerinde çalışıyor. Patch set burada: https://www.orioledb.com/docs#patch-set
Bu yılın sonlarında Supabase platformunda da denemeniz mümkün olacak