İçeriğe Atla
Mustafa Erbay
Teknoloji veritabani-derinlemesine · 10 dk okuma · görüntülenme Read in English

SQLite vs PostgreSQL: Üretim Ortamında Hangisi?

SQLite ve PostgreSQL'in üretim ortamındaki performans, concurrency, yedekleme ve kaynak tüketimi farklarını saha deneyimlerimle karşılaştırıyorum.

100%

Bir veritabanının üretim ortamına (production) uygun olup olmadığını belirleyen şey, pazarlama broşürlerindeki süslü kelimeler değil; diskteki kilitlenme mekanizmaları, bellek yönetimindeki kararlılığı ve eşzamanlı (concurrent) istekler altındaki davranışıdır. Yıllarca “SQLite sadece testler içindir, production’da illa PostgreSQL kullanacaksın” ezberini duyduk. Ancak işin aslı, her iki veritabanının da sınırlarını ve mimari yaklaşımlarını bilerek karar vermekten geçiyor. Kendi geliştirdiğim yan ürünlerde ve sahada yönettiğim sistemlerde her iki veritabanını da sınırlarına kadar zorlamış biri olarak, bu iki canavarın üretim ortamındaki gerçek performansını, avantajlarını ve sizi yarı yolda bırakabilecekleri kritik eşikleri masaya yatırmak istiyorum.

Bu yazıda teorik tanımlardan uzak durup doğrudan disk bloklarına, kilitlenme loglarına, RAM tüketimlerine ve operasyonel maliyetlere odaklanacağız. Eğer sunucu kaynaklarını optimize etmek, minimum bakım maliyetiyle maksimum verim almak istiyorsanız, doğru yerdesiniz.


Eşzamanlılık (Concurrency) ve Kilitlenme Mekanizmaları

SQLite ile PostgreSQL arasındaki en temel mimari ayrım, eşzamanlı yazma operasyonlarını nasıl yönettikleridir. PostgreSQL, MVCC (Multi-Version Concurrency Control) mimarisini kullanır. Bu sayede bir satır güncellenirken veya yazılırken, okuma yapan diğer işlemler asla engellenmez (non-blocking reads). PostgreSQL satır seviyesinde kilitleme (row-level locking) yaparak binlerce eşzamanlı yazma isteğini başarıyla koordine edebilir.

SQLite ise doğası gereği dosya tabanlı bir veritabanıdır. Standart DELETE veya TRUNCATE journal modlarında çalışırken, yazma işlemi yapabilmek için tüm veritabanı dosyasını kilitler. Ancak modern SQLite mimarisinde WAL (Write-Ahead Logging) modunu aktif ettiğinizde bu durum büyük oranda değişir. WAL modu, okuyucuların yazıcıları engellemesini, yazıcıların da okuyucuları engellemesini önler. Yine de aynı anda yalnızca tek bir yazma işlemi (single-writer) gerçekleştirilebilir.

Eğer saniyede yüzlerce eşzamanlı INSERT veya UPDATE alan bir uygulamanız varsa, SQLite üzerinde SQLITE_BUSY hatası almanız kaçınılmazdır. Bir yan ürünümün arka plan servislerinde eşzamanlı yazma hacmi belirgin şekilde arttığında SQLite loglarımda şu hatayı görmeye başlamıştım:

sqlite3.OperationalError: database is locked

Bu sorunu çözmek için SQLite bağlantı parametrelerinde journal_mode=WAL ve synchronous=NORMAL ayarlamalarını yapmak, ayrıca busy_timeout değerini 5000 ms gibi makul bir seviyeye çekmek geçici bir rahatlama sağlar. Ancak eşzamanlı yazma hacmi bu sınırın üzerine çıktığında, PostgreSQL’in satır bazlı kilit yönetimi ve gelişmiş lock manager yapısı tek gerçek çözüm haline gelir.


Bellek ve CPU Tüketimi: Bare-metal Performans Metrikleri

Üretim ortamında sunucu kaynaklarının maliyeti doğrudan cüzdanınıza yansır. Özellikle kendi VPS sunucularınızda mikro servisler veya yan projeler barındırıyorsanız, veritabanının boştayken (idle) ne kadar RAM tükettiği kritik bir parametredir.

PostgreSQL, zengin özellik seti ve bağlantı yönetimi nedeniyle ciddi bir bellek overhead’i ile gelir. PostgreSQL çalıştıran boş bir instance, hiçbir aktif bağlantı yokken bile işletim sisteminden kayda değer miktarda RAM rezerve eder. Her yeni istemci bağlantısı (client connection) için işletim sisteminde yeni bir process fork edilir ve bu da bağlantı başına ek bellek tüketimi demektir. Bağlantı havuzu (connection pooling) kullanmadığınız durumlarda, eşzamanlı bağlantı sayısı arttıkça RAM tüketimi hızla şişer.

SQLite ise uygulamanızın belleği içinde (in-process) çalışır. Ayrı bir servis veya process olmadığı için boştayken ekstra 1 KB bile RAM tüketmez. Uygulama kodunuzun hafıza alanını paylaşır. Bellek optimizasyonunu doğrudan SQLite cache_size pragması ile yönetebilirsiniz:

-- SQLite önbelleğini 10000 sayfa (yaklaşık 40MB) olarak ayarlama
PRAGMA cache_size = -10000;
PRAGMA page_size = 4096;

Daha önce PostgreSQL connection pool tuning yazımda bahsettiğim gibi, PostgreSQL tarafında bu bellek yükünü hafifletmek için PgBouncer gibi harici araçlar kullanmak zorunda kalırken, SQLite’ta bu tür ek operasyonel katmanlara hiç ihtiyaç duymazsınız. CPU tarafında ise, SQLite’ta network protokolü işlemleri (context switching, TCP paketleme) olmadığı için basit sorgularda PostgreSQL’e kıyasla belirgin oranda daha az CPU döngüsü harcanır.


Ağ Gecikmesi (Network Latency) ve IPC

PostgreSQL istemci-sunucu (client-server) mimarisine sahip bir veritabanıdır. Uygulama sunucunuz ile veritabanı sunucunuz farklı makinelerdeyse, her SQL sorgusu bir network paketine dönüştürülür, TCP/IP protokol yığınından geçer, ağ üzerinden taşınır ve hedef sunucuda işlenip geri döner. Bu durum, sorgu başına gözle görülür bir ağ gecikmesi (network round-trip time - RTT) ekler.

Eğer uygulamanız tek bir HTTP isteğini işlemek için arka arkaya çok sayıda SQL sorgusu atıyorsa (ki bu ORM kullanan sistemlerde çok sık karşılaşılan bir durumdur), sırf ağ gecikmesinden dolayı isteğin yanıt süresi belirgin biçimde uzar. PostgreSQL’i uygulama ile aynı sunucuya kurup Unix domain socket üzerinden bağlansanız bile, yine de IPC (Inter-Process Communication) overhead’inden kaçamazsınız.

SQLite’ta ise ağ diye bir şey yoktur. Veritabanı motoru, uygulamanızın derlenmiş kodunun bir parçasıdır. Bir sorgu çalıştırmak, bellekteki bir C fonksiyonunu çağırmaktan farksızdır. Gecikme süresi mikrosaniyeler seviyesindedir.

Aşağıdaki tabloda, yerel ağda (LAN) çalışan bir PostgreSQL ile aynı sunucuda koşan SQLite’ın basit SELECT sorgularındaki gecikme davranışını niteliksel olarak karşılaştırabilirsiniz (kesin rakamlar donanıma, ağa ve iş yüküne göre değişir):

Ölçüm Kriteri SQLite (WAL Modu) PostgreSQL (Unix Socket) PostgreSQL (LAN)
Tekil Satır Okuma En düşük Düşük Ağ RTT’si kadar artar
1000 Satır Bulk Read En düşük Düşük Ağ RTT’si kadar artar
Basit Write (INSERT) En düşük Düşük Ağ RTT’si kadar artar
Bellek Tüketimi (Idle) ~0 (in-process) Ayrı servis overhead’i Ayrı servis overhead’i

Veri Tipleri, Şema Esnekliği ve Katı Kurallar

PostgreSQL, veri tutarlılığı ve standartlara bağlılık konusunda tam bir disiplin abidesidir. Güçlü veri tipleri, CHECK kısıtları, custom enum tipleri ve JSONB desteği sayesinde veritabanı seviyesinde veri kalitesini garanti altına alır. PostgreSQL’de bir integer alanına yanlışlıkla string göndermeye çalışırsanız, veritabanı işlemi anında reddeder ve hata fırlatır.

SQLite ise geleneksel olarak “manifest typing” adı verilen esnek bir veri tipi sistemi kullanır. Yani veri tipi kolona değil, doğrudan o satırdaki değere atanır. SQLite’ta INTEGER olarak tanımladığınız bir kolona gidip "mustafa" string değerini yazabilirsiniz ve SQLite bunu sessizce kabul eder.

Ancak SQLite 3.37.0 (Kasım 2021) sürümüyle birlikte gelen STRICT tablolar bu durumu kökten değiştirdi. Artık üretim ortamında SQLite kullanırken veri tutarlılığından ödün vermek istemiyorsanız, tablolarınızı şu şekilde tanımlayabilirsiniz:

CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    username TEXT NOT NULL,
    age INTEGER,
    created_at TEXT
) STRICT;

STRICT anahtar kelimesi eklendiğinde, SQLite tıpkı PostgreSQL gibi davranır ve tip uyuşmazlıklarında hata döndürür. Yine de PostgreSQL’in zengin veri tipleri (örneğin UUID, INET, native JSONB indeksleme yetenekleri ve gelişmiş tarih-saat fonksiyonları) karmaşık kurumsal uygulamalarda, özellikle bir üretim ERP’si veya finansal sistemler geliştirirken PostgreSQL’i vazgeçilmez kılar.


Yedekleme, Replikasyon ve High Availability (HA)

Üretim ortamındaki en büyük korku veri kaybıdır. PostgreSQL bu konuda endüstrinin altın standartlarından biridir. pg_dump ile canlı sistemden sıfır kesintiyle yedek alabilir, WAL segmentlerini uzak bir depolama alanına (örneğin S3) stream ederek Point-in-Time Recovery (PITR) kurulumu yapabilirsiniz. Yani veritabanınızı geçmişteki belirli bir ana kadar geri döndürmeniz mümkündür. Ayrıca master-replica mimarisiyle okuma yükünü dağıtabilir ve otomatik failover mekanizmaları kurabilirsiniz.

SQLite ise tek bir dosyadan ibaret olduğu için yedeklemesi ilk bakışta kolay görünür: “Dosyayı kopyala gitsin.” Ancak canlı yazma işlemleri devam ederken doğrudan işletim sistemi seviyesinde cp komutuyla dosyayı kopyalamaya çalışırsanız, bozuk (corrupted) bir yedek dosyası elde etme riskiniz çok yüksektir.

SQLite’ı güvenli bir şekilde yedeklemek için SQLite’ın kendi online backup API’sini veya CLI aracını kullanmanız gerekir:

sqlite3 /var/lib/data/prod.db ".backup /backup/backup-$(date +%F).db"

Son yıllarda SQLite ekosisteminde devrim yaratan litestream gibi araçlar sayesinde artık SQLite için de gerçek zamanlı replikasyon mümkün hale geldi. Litestream, SQLite’ın WAL dosyalarını arka planda dinleyerek her transaction sonrasında değişiklikleri saniyeler içinde AWS S3 veya benzeri bir nesne depolama servisine stream eder.

Yine de, birden fazla coğrafi bölgede (multi-region) aktif-aktif çalışan veya saniyede binlerce yazma işlemi yapan yüksek erişilebilirlikli (High Availability) bir mimariye ihtiyacınız varsa, PostgreSQL’in olgunlaşmış replikasyon araçlarının yanına SQLite + Litestream ikilisi henüz yaklaşamaz.


Karar Matrisi: Hangi Senaryoda Hangisini Seçtim?

Uygulama mimarisi tasarlarken “en iyi veritabanı” yoktur, “doğru senaryo için doğru veritabanı” vardır. Kendi projelerimde ve sahada yaptığım kurulumlarda bu seçimi yaparken kullandığım basit ama etkili karar matrisini sizinle paylaşayım.

SQLite Tercih Ettiğim Durumlar:

  1. Düşük Kaynaklı VPS Kurulumları: Aylık 5 USD maliyetli, 1 GB RAM’e sahip bir VPS üzerinde birden fazla küçük servis koşturuyorsam, PostgreSQL’in bellek israfıyla uğraşmamak için kesinlikle SQLite (WAL modunda) tercih ederim.
  2. Okuma Ağırlıklı (Read-Heavy) Uygulamalar: İçerik yönetim sistemleri (CMS), statik veri sunan API’ler veya kişisel bloglar gibi yazma oranının %5’in altında olduğu senaryolarda SQLite’ın hızı rakipsizdir.
  3. Edge ve IoT Cihazları: İnternet bağlantısının kopabileceği, verinin yerelde birikip sonra senkronize edileceği saha operasyonlarında SQLite tek seçenektir.

PostgreSQL Tercih Ettiğim Durumlar:

  1. Çoklu Yazıcı (High Write Concurrency): Aynı anda yüzlerce farklı kullanıcının veya arka plan işçisinin (Celery/Sidekiq worker’ları) sürekli veritabanına yazma yaptığı sistemler.
  2. Karmaşık Analitik Sorgular ve Raporlama: WINDOW fonksiyonlarının yoğun kullanıldığı, büyük veri kümeleri üzerinde karmaşık JOIN operasyonlarının döndüğü, bir üretim ERP’sinin planlama modülleri gibi yerlerde PostgreSQL’in query planner’ı harikalar yaratır.
  3. Katı Veri Şeması ve Güvenlik: Row-Level Security (RLS) ihtiyacı olan, kullanıcı bazlı veri erişim kısıtlamalarının veritabanı seviyesinde yapılması gereken çok kiracılı (multi-tenant) kurumsal SaaS uygulamaları.

Daha önce kaleme aldığım Yazılım mimarisi ve organizasyonel akış yazısında değindiğim gibi, teknoloji seçimlerini popüler trendlere göre değil, organizasyonunuzun operasyonel yetkinliklerine ve bütçesine göre yapmalısınız. PostgreSQL harika bir veritabanıdır ancak yönetmesi, yedeklemesi, connection limitlerini ayarlaması ve optimize etmesi ciddi bir mesai gerektirir. SQLite ise “kur ve unut” felsefesine en yakın, operasyonel yükü sıfıra yakın bir mühendislik harikasıdır. Sınırlarını bildiğiniz sürece, her ikisi de üretim ortamında canavar gibi çalışacaktır. Tercihinizi yaparken uygulamanızın yazma yükünü ve ekibinizin operasyonel tecrübesini dürüstçe değerlendirin.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

Sıkça Sorulanlar

Bu makale ile ilgili okurların sorduğu yaygın sorular.

SQLite ve PostgreSQL arasında eşzamanlılık (concurrency) açısından hangi farklar vardır?
PostgreSQL MVCC mimarisini kullanır ve satır seviyesinde kilitleme yaparak binlerce eşzamanlı yazma isteğini başarıyla koordine edebilir. SQLite ise doğası gereği dosya tabanlı bir veritabanıdır ve yazma işlemi yapabilmek için tüm veritabanı dosyasını kilitler. Bu nedenle, yüksek eşzamanlılık gerektiren uygulamalar için PostgreSQL daha uygun olabilir.
Üretim ortamında SQLite yerine PostgreSQL kullanmanın avantajları nelerdir?
Benim deneyimimde, PostgreSQL'in avantajları arasında daha iyi eşzamanlılık desteği, daha yüksek verimlilik ve daha geniş ölçeklenebilirlik bulunmaktadır. Ayrıca, PostgreSQL daha gelişmiş bir veritabanı yönetim sistemidir ve daha fazla özellik sunar. Ancak, bu avantajlar daha yüksek kaynak gereksinimi ve daha karmaşık kurulum ile karşılıklı olabilir.
SQLite'i üretim ortamında kullanırken dikkat edilmesi gereken kritik eşikler nelerdir?
SQLite'i üretim ortamında kullanırken dikkat edilmesi gereken kritik eşiklerden biri, eşzamanlılık sınırıdır. SQLite, yüksek eşzamanlılık gerektiren uygulamalar için uygun değildir ve bu nedenle, uygulamanızın eşzamanlılık gereksinimlerini dikkatlice değerlendirmelisiniz. Ayrıca, SQLite'in kaynak tüketimi ve veritabanı boyutu da dikkate alınmalıdır.
Üretim ortamında PostgreSQL'i optimize etmek için hangi adımlar atılmalıdır?
Üretim ortamında PostgreSQL'i optimize etmek için atılması gereken adımlardan biri, sunucu kaynaklarını optimize etmektir. Bu, yeterli RAM ve CPU kaynağı ayırarak ve veritabanı parametrelerini ayarlayarak yapılabilir. Ayrıca, düzenli olarak veritabanı yedeklemesi yapmak, indeksleri güncellemek ve sorguları optimize etmek de önemlidir. Bu adımlar, PostgreSQL'in performansı ve verimliliğini artırabilir.
ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Yorumlar

Sunucu Taraflı AI Moderasyon

Yorumlar sunucuda yapay zeka ile denetlenir ve kalıcı olarak saklanır.

?
0/2000

Sunucu taraflı AI denetim

✉️ Ücretsiz · Spam yok · İstediğin an çık

Yeni yazılardan haberdar olun

Yeni içerikler ve teknik notlar e-postanıza gelsin.

  • 📌
    Haftanın en iyisi Sadece okumaya değer tek yazı
  • 🔧
    Alet çantası Bu hafta kullandığım araçlar
  • 🧠
    Perde arkası Blog'a girmeyen notlar

Spam yapmıyoruz. İstediğiniz zaman ayrılabilirsiniz. · Sadece Umami (self-hosted, Google yok) ile takip.

Okuma İstatistikleriniz

0

Yazı Okundu

0dk

Okuma Süresi

0

Gün Serisi

-

Favori Kategori

İlgili Yazılar