27 puan yazan GN⁺ 2025-12-03 | 2 yorum | WhatsApp'ta paylaş
  • SQLite'ın tek yazarlı yapısı ve gömülü niteliğinin aslında ölçeklenebilirlik ve performansı artıran etkenler olduğu deneylerle gösterildi
  • Aynı koşullarda Postgres ağ gecikmesi olduğunda 348 TPS'ye kadar düşerken, SQLite ağın ortadan kalkmasıyla 44.096 TPS'ye ulaştı
  • Tek yazarlı modelden yararlanan batch işleme ve SAVEPOINT tabanlı ayrıntılı transaction'larla en fazla 186.157 TPS, kararlı yapılandırmada ise 102.545 TPS kaydedildi
  • Amdahl yasası, ağ tabanlı veritabanlarındaki darboğazı açıklarken, SQLite bunu aşarak yüksek verimliliği koruyor
  • Bu sonuçlar, yerel ortamda SQLite kullanımının potansiyelini ve ağ darboğazını ortadan kaldırmanın önemini vurguluyor

SQLite'ın yapısı ve deney ortamı

  • SQLite MVCC kullanmıyor ve yalnızca tek bir yazara izin veriyor, ancak bu yapı ironik biçimde yüksek ölçeklenebilirliği mümkün kılıyor
    • Gömülü bir veritabanı olduğundan ağ ek yükü yok
  • Benchmark, Apple M1 Pro, 16 GB bellekli MacBook Pro (2021) ortamında yürütüldü
  • Deney, kusursuz optimizasyonu hedeflemekten çok, genel koşullarda da yüksek yazma throughput'una ulaşılabildiğini göstermek amacıyla yapıldı

TPS tanımı ve transaction örneği

  • TPS, basit bir yazma hızı değil, etkileşimli transaction (Interactive Transaction) anlamına geliyor
    • Örnek: Hesaplar arasında para transferinde birden fazla sorgu ve uygulama kodu tek bir transaction içinde çalışır
  • Transaction'lar hata oluştuğunda durumu geri alabilir; bu yüzden tutarlılığın korunmasında kritik rol oynar

Benchmark yapısı

  • Büyük ölçekli eşzamanlı istekleri simüle etmek için Clojure tabanlı virtual threads kullanıldı
  • Postgres, HikariCP tabanlı connection pool ile yapılandırılırken, SQLite tek yazar ve çekirdek sayısı kadar okuma bağlantısı kullandı
  • Her iki veritabanında da id, balance alanlarına sahip basit bir account tablosu kullanıldı ve 1 milyar satır eklendi
  • Kullanıcı etkinliği power law dağılımını (0.9995) izliyor ve yaklaşık 100 bin aktif kullanıcı bulunuyor

Ağ tabanlı veritabanı (Postgres) performansı

  • Aynı sunucuda Postgres 13.756 TPS elde etti
  • 5 ms ağ gecikmesi eklendiğinde 1.214 TPS'ye, 10 ms'de ise 702 TPS'ye sert biçimde düştü
  • Serialization isolation level uygulandıktan sonra 660 TPS'ye, ek sorgular dahil edildiğinde ise 348 TPS'ye geriledi
  • Bu, Amdahl yasasına göre ağ darboğazının toplam performansı sınırladığını gösteriyor
    • Ağ gecikmesi arttıkça transaction lock çekişmesi yoğunlaşıyor ve sistem ölçeklenemiyor

SQLite'ın gömülü olmasının avantajı

  • Ağ ortadan kaldırıldığında SQLite 44.096 TPS'ye ulaştı
    • Ağ darboğazı kaybolduğu için Amdahl yasasının etkisi en aza indi
  • Tek yazarlı yapıdan yararlanılarak batch processing uygulandığında değer 186.157 TPS'ye kadar çıktı
    • Dinamik batch boyutu ayarıyla latency ve throughput otomatik olarak optimize edildi

SAVEPOINT ile ayrıntılı transaction'lar

  • Batch içindeki tekil transaction hatalarının tüm işlemi bozmasını önlemek için SAVEPOINT kullanan iç içe transaction'lar uygulandı
    • Hata durumunda yalnızca ilgili transaction geri alınıyor, tüm batch korunuyor
  • Bu yöntemle de 121.922 TPS korundu

Okuma/yazma karma yük testi

  • Tüm isteklerin %75'i okuma, %25'i yazma olarak yapılandırıldı
  • Ayrı bir okuma thread pool kullanılarak okuma isteklerinin yazmaları engellememesi için ayrıştırma yapıldı
  • Sonuç olarak 102.545 TPS elde edildi

Performans karşılaştırması özeti

Koşul Postgres SQLite
Ağ yok 13.756 44.096
5 ms gecikme 1.214 n/a
10 ms gecikme 702 n/a
10 ms + serialization 660 n/a
Batch işleme n/a 186.157
Batch + SAVEPOINT n/a 121.922
Batch + SAVEPOINT + okuma n/a 102.545

Sonuç

  • SQLite, tek yazarlı model ve gömülü yapı sayesinde ağ tabanlı veritabanlarına kıyasla çok daha yüksek TPS elde etti
  • Amdahl yasasının işaret ettiği ağ darboğazı sınırını aşarak verimliliği en üst düzeye çıkardı
  • Tüm kod GitHub'da açıklandı ve ilgili başlıklar kapsamında Amdahl yasası, power law, SQLite ölçeklendirme örnekleri gibi kaynaklar da sunuldu
  • SQLite, yerel ortamda yüksek performanslı transaction işleme için son derece etkili bir seçenek

2 yorum

 
ppp123 2025-12-10

Harici sunucuya gitmeden yalnızca yerel ortamda kullanılacaksa, ağ diye bir vergi ödemeye gerek var mı demek oluyor. (VFS vs Socket)

 
GN⁺ 2025-12-03
Hacker News yorumu
  • SQLite tabanlı hibrit protobuf ORM/CRUD sunucusu geliştiriyorum
    Kod ve açıklamalar GitHub - accretional/collector üzerinde
    Gerçek zamanlı yedeklemede 5~15 ms kesinti, yüzlerce okuma/yazma isteğinin kuyruklanması, CRUD genel gecikmesinde yaklaşık 1 ms ve WAL tabanlı streaming yedekleme bile mümkün
    Eskiden yalnızca Postgres ve Spanner kullanıyordum; Collector'a bölümleme özelliği eklenirse muhtemelen bir daha Postgres kullanmam

    • BTRFS gibi atomic snapshot destekli bir dosya sistemi kullanarak SQLite + WAL ile sıfır kesintili yedekleme yapmayı düşünüp düşünmediğini merak ediyorum. Snapshot aldıktan sonra yedeği yavaşça alıp silmek yeterli
  • Dezavantajı, tüm veri ve işlemlerin tek bir makineye sığmak zorunda olması
    AWS'nin u-24tb1.112xlarge instance'ı (448 vcore, 24 TB RAM, 64 TB EBS) kullanılırsa oldukça geniş bir alan var

    • Ama Hetzner bare metal sunucu kiralanırsa çekirdek başına performans 2~3 kat artıyor, maliyet ise %90 azalıyor
    • SQLite'ın teorik maksimum veritabanı boyutunun 281 TB olduğu resmî belgede belirtiliyor. Pratikte dosya sistemi sınırı daha düşük ama yine de çalışıyor
    • Tek makineyi dikey ölçeklemek güvenilir ama esneklik (elasticity) açısından zayıf. Trafik aniden artarsa ya fazla kaynak ayırmak ya da arızayı göze almak gerekiyor
    • “Veriniz RAM'e sığıyor mu?” diye soran yourdatafitsinram.net bağlantısına bakınca, yüksek performanslı tek düğüm için EC2 yerine dedicated sunucunun daha iyi olduğunu düşünüyorum
  • Yazı SQLite'ın verimliliğini vurguluyor ama karşılaştırma ölçütünün belirsiz olduğunu düşünüyorum
    Çünkü baştan ayrı sunucu mimarisi varsayılmış, sonra da yerel gömülü veritabanı performansı ölçülmüş
    Aynı koşullarda yerel Postgres tuning ile de benzer performans elde edilebilir

    • SQLite, aynı makinedeki Postgres'ten de daha hızlıdır. Testleri gerçek production ortamı yapılandırmasına göre yapmak daha doğru olur
    • SQLite'ı istek işleyicisinin arkasına sararak başka bir sunucuda da çalıştırabilirsiniz. Sonuçta veritabanı, istek işleyicisi ile depolamanın birleşimidir
    • Tek kutuda ham throughput önemlidir. SQLite, PG'den 10 kat hızlıdır ve PG, transaction karmaşıklığı arttıkça yavaşlar
    • “O zaman SQLite bir karşılaştırma hedefi değil” demek fazla basit olur. O durumda yazı çok kısa kalırdı
    • SQLite yalnızca mobil ya da embedded için değil, düşük eşzamanlılığa sahip sunucu uygulamaları için de uygundur. Sadece web sunucuları için bir veritabanı değildir
  • Postgres bağlantı sayısını 8 ile sınırlamak bir darboğaz olabilir
    CPU ve thread kullanımını da paylaşıp, daha büyük bir connection pool ile yeniden test etmek iyi olur

    • Connection pool'u çekirdek sayısına (8) göre ayarlamak makul ama transaction içinde sleep varsa darboğaz oluşur
      64 bağlantıya çıkarılırsa throughput 8 kat artabilir. Sınıra ulaşana kadar istemci ayarlarını ölçeklemek gerekir
    • Bu yazıdaki rakamlara inanmak zor. Ben network tabanlı MySQL'de bile çok daha yüksek TPS alıyorum
  • Asıl nokta, network gecikmesinin darboğaz olup olmadığını fark etmek
    Birçok iş yükünde sıradan bir yerel veritabanı, mükemmel bir uzak veritabanından daha hızlıdır
    Önemli olan “hangi veritabanı en iyisi” değil, “network sınırını geçmek zorunda mısınız” sorusudur

    • (Yazar) Doğru. Niyetim SQLite vs Postgres tartışması değil, network tabanlı veritabanlarının sınırlarını ele almaktı
    • Elbette her şeyi bellekte tutup Redis veya Memcache kullanırsanız performansı kolayca artırabilirsiniz. Ama bu durumda kurallar değişmiş olur
  • Network tipi veritabanları, uygulamayı yeniden dağıtmayı kolaylaştırma avantajına sahip
    Yeni bir instance açıp eskisini kapatarak neredeyse kesintisiz dağıtım yapmak mümkün
    SQLite aynı instance üzerinde olursa değişim sırasında veritabanını da yeniden ayağa kaldırmak gerekir; bu da daha karmaşık hale gelir. Gerçek operasyonda böyle bir sorun yaşanıp yaşanmadığını merak ediyorum

    • SQLite'ı production'da kullanmak için kalıcı depolama ve NVMe gerekir. Genellikle bare metal tek sunucu olarak çalıştırılır
      Migration sırasında kesinti olabilir. Litestream sayesinde artık replikasyon ve yedekleme daha kolay
    • SQLite çoklu process erişimini desteklediği için, yeni process başlatıp eskisini kapatma şeklinde kesintisiz değişim de mümkündür
  • Yazar PRAGMA synchronous="normal" ayarını kullanmış; bu, her seferinde fsync yapılmadığı anlamına gelir
    Adil bir karşılaştırma için "full" olarak ayarlanması gerekir

    • Ama WAL modunda "normal" de kabul edilebilir. Güç kaybında dayanıklılık kaybedilir ama transaction tutarlılığı korunur
  • SQLite için HA (yüksek erişilebilirlik) yapılandırmasının nasıl olduğunu merak ediyorum
    En azından otomatik failover yapılabilecek bir düzey olmalı

    • SQLite bir C kütüphanesi olduğu için, rqlite, litestream, litefs gibi projelerle genişletilebilir
      Ben şu anda Postgres ile SQLite (litestream dahil) arasında kararsızım.
      Uygulamam bir miktar kesintiyi tolere edebildiği için, tek kutuda dikey ölçekleme daha basit ve daha ucuz
    • Son dönemde Marmot adlı bir multi-master proje 2 yıl sonra yeniden canlandırıldı.
      Marmot GitHub üzerinde gossip tabanlı replikasyon mekanizması yeni eklendi
  • SQLite'ı gerçekten production'da sınırlarına kadar zorlayan örnekler olup olmadığını merak ediyorum

  • Tipik bir web uygulaması veya e-ticaret ortamında SQLite ile Postgres arasında kullanıcı sayısı sınırının yaklaşık nerede olduğunu merak ediyorum
    SQLite son güncellemelerle eşzamanlı okumayı destekliyor ama hâlâ yalnızca tek yazmaya izin veriyor
    Bunun hangi durumlarda sorun olduğunu ve ölçekleme düşünülüyorsa baştan Postgres ile başlamanın daha doğru olup olmadığını sormak isterim