PostgreSQL vs MariaDB for Transactional CRUD Apps
PostgreSQL vs MariaDB: indeksleme, göçler, JSON ve CRUD uygulamanız prototipi aştığında önem kazanan sorgu özelliklerine pratik bir bakış.

Bir CRUD uygulaması prototipi aştığında
Bir prototip CRUD uygulaması genellikle hızlı hisseder çünkü veri küçüktür, ekip azdır ve trafik öngörülebilirdir. Basit sorgular, birkaç indeks ve manuel şema düzeltmeleriyle idare edebilirsiniz. Sonra uygulama gerçek kullanıcılar, gerçek iş akışları ve gerçek teslim tarihlerine kavuşur.
Büyüme iş yükünü değiştirir. Listeler ve paneller tüm gün açılır. Daha fazla kişi aynı kayıtları düzenler. Arka plan işleri toplu yazmaya başlar. İşte "dün çalışıyordu" demeniz, yavaş sayfalar, rastgele zaman aşımı ve yoğun saatlerde kilit beklemelerine dönüşür.
Muhtemelen şu tür şeyleri görüyorsanız çizgiyi geçmişsinizdir: sayfa 20’den sonra yavaşlayan liste sayfaları, yayınların veri doldurmalarını (sadece yeni sütun değil) içermesi, meta veriler ve entegrasyon yükleri için artan “esnek alanlar” veya yoğun zamanlarda “kaydetme çok uzun sürüyor” diyen destek talepleri.
İşte o zaman PostgreSQL ile MariaDB karşılaştırması marka tercihi olmaktan çıkar ve pratik bir soruya dönüşür. İşlemsel CRUD iş yüklerinde sonucu genellikle belirleyen ayrıntılar, sorgular karmaşıklaştıkça öne çıkan indeksleme seçenekleri, tablolar büyükken göçlerin güvenliği, JSON depolama ve sorgulama ile uygulama tarafı iş yükünü azaltan sorgu özellikleridir.
Bu yazı bu veritabanı davranışlarına odaklıdır. Sunucu boyutlandırma, bulut fiyatlandırması veya tedarikçi sözleşmeleri derinlemesine ele alınmaz. Bunlar önemli olsa da, ürününüzün bağımlı olduğu şema ve sorgu stilinden sonra değiştirilmesi genellikle daha kolaydır.
Veritabanı markasıyla değil, uygulama gereksinimlerinizle başlayın
Daha iyi başlangıç noktası “PostgreSQL vs MariaDB” değil: uygulamanızın günlük davranışıdır: kayıt oluşturma, birkaç alan güncelleme, filtrelenmiş sonuçları listeleme ve birçok kişinin aynı anda tıklamasında doğruluk.
En yoğun ekranlarınızın ne yaptığını yazın. Her yazma için kaç okuma oluyor? Sıçramalar ne zaman meydana geliyor (sabah girişleri, ay sonu raporlaması, büyük içe aktarımlar)? İleride indeks tasarımını ve sorgu örüntülerini yönlendirecek kesin filtreleri ve sıralamaları yakalayın.
Sonra vazgeçilmezlerinizi tanımlayın. Pek çok ekip için bu, para veya envanter için sıkı tutarlılık, “kim neyi değiştirdi” için bir audit trail ve şema evrildikçe rapor sorgularının bozulmaması demektir.
Operasyonel gerçeklik özellikler kadar önemlidir. Yönetilen bir veritabanı mı çalıştıracağınıza yoksa kendi kendinize mi barındıracağınıza, yedekten ne kadar hızlı geri dönmeniz gerektiğine ve bakım pencerelerine ne kadar tolerans gösterdiğinize karar verin.
Son olarak, birkaç net hedefle “yeterince hızlı”yı tanımlayın. Örneğin: normal yük altında p95 API gecikmesi (200–400 ms), yoğun eşzamanlılık altında p95 (normalin belki 2x’i), güncellemeler sırasında kabul edilebilir maksimum kilit beklemesi (100 ms altında) ve yedekleme ve geri yükleme zaman limitleri.
CRUD hızını belirleyen indeksleme temel bilgileri
Çoğu CRUD uygulaması tablolar milyonlarca satıra ulaşana ve her ekran "filtrelenmiş bir liste ve sıralama" hâline gelene kadar hızlı hisseder. O noktada indeksleme, 50 ms’lik bir sorgu ile 5 saniyelik bir zaman aşımı arasındaki farktır.
B-tree indeksleri her iki veritabanında varsayılan iş atlıdır. Bir sütuna göre filtrelediğinizde, anahtarlarda join yaptığınızda ve ORDER BY indeks sırasına uyduğunda yardımcı olurlar. Gerçek performans farkı genellikle seçiciliğe (kaç satır eşlendiğine) ve indeksin filtreleme ile sıralamayı tarama yapmadan sağlayıp sağlayamadığına bağlıdır.
Uygulamalar olgunlaştıkça bileşik indeksler tek sütunlu indekslerden daha önemli olur. Yaygın bir desen çoklu kiracı filtreleme artı durum artı zaman sıralaması gibi (tenant_id, status, created_at) biçimindedir. En tutarlı filtreyi öne koyun (genellikle tenant_id), sonra sonraki filtre, sonra sıraladığınız sütun. Bu, optimizörün verimli şekilde birleştiremeyeceği ayrı indekslerden genelde daha iyidir.
Farklılıklar “daha akıllı” indekslerde görünür. PostgreSQL, belirli ekranlar için harika olabilen partial ve expression indekslerini destekler (örneğin yalnızca “açık” biletleri indekslemek). Bunlar güçlüdür, ama sorgular predikata tam uymazsa takılabilirler.
İndekslerin bedeli vardır. Her insert ve update her indeksi de güncellemelidir, bu yüzden bir ekranı hızlandırırken her yazmayı gizlice yavaşlatmak kolaydır.
Disiplinli kalmanın basit bir yolu:
- Bir indeksi yalnızca gerçek bir sorgu yolu (isimlendirebileceğiniz bir ekran veya API çağrısı) için ekleyin.
- Birçok örtüşen indekstense bir iyi bileşik indeks tercih edin.
- Özellik değişikliklerinden sonra indeksleri yeniden gözden geçirip gereksizleri kaldırın.
- Bakım planlayın: PostgreSQL şişmeyi önlemek için düzenli vacuum/analyze ister; MariaDB de iyi istatistikler ve ara temizliklere dayanır.
- Sezgilere güvenmek yerine önce ve sonra ölçün.
Gerçek ekranlar için indeksleme: listeler, arama ve sayfalama
Çoğu CRUD uygulaması zamanını birkaç ekranda geçirir: filtreli bir liste, bir arama kutusu ve bir detay sayfası. Veritabanı seçiminiz, indekslerin bu ekranlara uyup uymadığı kadar önemli olmayabilir, ama tablolar büyüdükçe iki motor size farklı araçlar sağlar.
Liste sayfaları için şu sırayı düşünün: önce filtre, sonra sıralama, sonra sayfalama. Yaygın bir desen "hesap X için tüm biletler, status in (open, pending), en yeniden önce" gibidir. Filtre sütunlarıyla başlayan ve sıralama sütunuyla biten bileşik bir indeks genelde kazanır.
Sayfalama özel ilgi ister. Offset sayfalama (OFFSET 380 ile sayfa 20) kaydırdıkça yavaşlar çünkü veritabanı önceki satırlardan geçmek zorunda kalır. Keyset sayfalama daha dengelidir: son görülen değeri (created_at ve id gibi) geçirirsiniz ve “ondan daha eski 20” istersiniz. Bu yeni satırlar gelince tekrarları ve boşlukları azaltır.
PostgreSQL, görünürlük haritası izin verdiğinde index-only scan yapabilen INCLUDE ile “covering” indeksler için kullanışlı bir seçenek sunar. MariaDB de covering read yapabilir, ama genelde gerekli sütunları doğrudan indeks tanımına koyarak bunu sağlarsınız. Bu da indeksleri daha geniş ve bakım maliyetli yapabilir.
Tablo büyüdüğünde, sadece 20–50 satırlık sonuç döndüren bir liste uç noktasının yavaşlaması, sıralamanın ORDER BY kaldırılınca hızlanması veya basit filtrelerde I/O artışı görüyorsanız daha iyi indekslere ihtiyacınız vardır. Uzun sorgular yoğun dönemlerde kilit beklemelerini de artırır.
Örnek: customer_id ve status ile filtreleyen ve created_at ile sıralayan bir sipariş ekranı genellikle (customer_id, status, created_at) ile başlamaktan fayda görür. Sonradan “sipariş numarasına göre arama” ekliyorsanız, genelde bunun için ayrı bir indeks gerekir; liste indeksine her şeyi eklemek doğru değildir.
Göçler: veri büyüdükçe yayınları güvenli tutmak
Göçler çabukça "bir tabloyu değiştir" olmaktan çıkar. Gerçek kullanıcılar ve geçmiş varken veri doldurmalar, kısıtlamaların sıkılaştırılması ve eski veri şekillerinin uygulamayı kırmadan temizlenmesi gerekir.
Güvenli bir varsayılan, genişlet, doldur (backfill), daralt taktiğidir. İhtiyacınız olanı, mevcut kodu bozmadan ekleyin, veriyi küçük adımlarla kopyalayın veya hesaplayın, sonra eskisini kaldırın.
Pratikte bu genelde yeni nullable bir sütun veya tablo eklemek, yazmaları tutarlı tutarken küçük gruplar halinde backfill yapmak, daha sonra NOT NULL, foreign key ve unique kuralları gibi kısıtlamalarla doğrulamak ve ancak sonra eski sütunları, indeksleri ve kod yollarını kaldırmaktır.
Tüm şema değişiklikleri eşit değildir. Bir sütun eklemek genellikle düşük risklidir. Büyük tablolar üzerinde bir indeks eklemek pahalı olabilir; bunun için düşük trafikli zaman planlayın ve ölçüm yapın. Sütun tipini değiştirmek çoğunlukla en riskli olanıdır çünkü veri yeniden yazılabilir veya yazmaları engelleyebilir. Daha güvenli bir desen genelde: yeni tipte yeni bir sütun oluştur, backfill yap, sonra okuma ve yazmaları ona geçiştir.
Geri alma (rollback) da ölçekle anlam değiştirir. Şema geri almak bazen kolaydır; veri geri almak genellikle kolay değildir. Yayına alımda yıkıcı silme veya bilgi kaybına yol açan dönüşümler varsa neyi geri alabileceğiniz konusunda açık olun.
JSON desteği: gelecekte acı çekmeden esnek alanlar
JSON alanları, ekstra form alanları, entegrasyon payload’ları, kullanıcı tercihleri ve dış sistem notlarını şemayı değiştirmeden koyabildiğiniz için caziptir. İş, JSON’da neyin kalacağı ve neyin gerçek sütun olacağına karar vermektir.
Hem PostgreSQL hem MariaDB’de JSON genellikle nadiren filtrelenen ve çoğunlukla görüntülenen, hata ayıklama için saklanan, kullanıcı veya kiracı başına bir “ayar” blob’u ya da raporlama yapmayan küçük isteğe bağlı öznitelikler için en iyi sonucu verir.
JSON’un indekslenmesi ekipleri şaşırtır. Bir JSON anahtarını bir kere sorgulamak kolaydır. Büyük tablolar üzerinde onu filtrelemek ve sıralamak performansın çökmesine yol açabilir. PostgreSQL, JSON yollarını indekslemek için güçlü seçenekler sunar, ama disiplin gerekir: gerçekten filtrelediğiniz birkaç anahtarı seçip onları indeksleyin, geri kalanları indekslenmemiş yük olarak tutun. MariaDB de JSON sorgulayabilir, ama JSON içinde karmaşık arama desenleri genellikle kırılgan ve performansını koruması zor hale gelir.
JSON ayrıca kısıtlamaları zayıflatır. Yapısal olmayan bir blob içinde “bunlardan biri olmalı” veya “her zaman mevcut” gibi kuralları uygulamak daha zordur; raporlama araçları genelde tipli sütunları tercih eder.
Ölçeklenen bir kural: bilinmeyenler için JSON ile başlayın, ama (1) onu filtreliyor veya sıralıyorsanız, (2) kısıtlamalara ihtiyacınız varsa ya da (3) haftalık panolarda görüyorsanız sütunlar veya child tablolara normalleştirin. Bir siparişin tam kargo API cevabını JSON olarak saklamak genelde iyidir. Ancak delivery_status ve carrier gibi alanlar destek ve raporlama bağımlı hale gelince gerçek sütunları hak eder.
Olgunlaşmış uygulamalarda öne çıkan sorgu özellikleri
Erken dönemde çoğu CRUD uygulaması basit SELECT, INSERT, UPDATE ve DELETE ile gider. Sonra aktivite akışları, audit görünümleri, yönetici raporları ve anlık hissettiren arama ihtiyaçları eklenir. İşte seçim bir özellik takasına dönüşür.
CTE’ler ve alt sorgular karmaşık sorguları okunabilir tutmaya yardımcı olur. Sonuçları adım adım inşa ederken yararlıdırlar (siparişleri filtrele, ödemeleri join et, toplamları hesapla). Ancak okunabilirlik maliyeti gizleyebilir. Bir sorgu yavaşladığında CTE’yi alt sorgu veya join’e çevirip yürütme planını tekrar kontrol etmeniz gerekebilir.
Pencere (window) fonksiyonları, birileri "müşterileri harcamaya göre sırala", "çalışan toplamları göster" veya "bilet başına en son durum" istediğinde önemli olur. Genellikle uygulama döngülerini azaltır ve sorgu sayısını düşürür.
Idempotent yazmalar başka bir olgunluk gereksinimidir. Yeniden denemeler olduğunda çift kayıt oluşturmayı önlemek için upsert’ler gerekir:
- PostgreSQL:
INSERT ... ON CONFLICT - MariaDB:
INSERT ... ON DUPLICATE KEY UPDATE
Arama (search) ekipleri sessizce yakalar. Yerleşik full-text search ürün katalogları, bilgi tabanları ve destek notları için yeterli olabilir. Trigram benzeri aramalar type-ahead ve yazım hatalarına karşı tolerans sağlar. Arama çekirdek haline gelirse (karmaşık sıralama, çok filtre, yoğun trafik), harici bir arama aracı ekstra karmaşıklığa rağmen değebilir.
Örnek: bir sipariş portalı "siparişleri listele" ile başlar. Bir yıl sonra "her müşterinin en son siparişini göster, aylık harcamaya göre sırala ve yanlış yazılmış isimlerle arama yap" ihtiyaçları çıkar. Bunlar sadece UI işi değil, veritabanı kabiliyetleridir.
Yük altındayken işlemler, kilitler ve eşzamanlılık
Trafik düşükken çoğu veritabanı iyi görünür. Yük altındayken fark genellikle ham hızda değil, aynı veriyi eşzamanlı değiştirme şeklinizde olur. Hem PostgreSQL hem MariaDB bir işlemsel CRUD iş yükünü çalıştırabilir, ama hakimiyet tasarımı yine de önemlidir.
İzolasyonu sade dilde anlatmak
Bir işlem (transaction) birlikte başarılı olması gereken adımlar dizisidir. İzolasyon başka oturumların bu adımlar çalışırken neleri görebileceğini kontrol eder. Daha yüksek izolasyon şaşırtıcı okumaları azaltır ama beklemeyi artırabilir. Birçok uygulama varsayılanlarla başlar ve gerçekten ihtiyaç duyulan akışlar (ör. kartı tahsil edip siparişi güncelleme) için izolasyonu sıkılaştırır.
Kilit sorunlarına gerçekten ne sebep olur
CRUD uygulamalarında kilit problemleri genellikle birkaç tekrar eden suçludan kaynaklanır: herkesin güncellediği sıcak satırlar, her eylemde değişen sayaçlar, birçok çalışanın aynı "sonraki işi" almaya çalıştığı iş kuyrukları ve diğer işlerin (veya kullanıcı zamanının) geçtiği uzun işlemler.
Çakışmayı azaltmak için işlemleri kısa tutun, sadece gereken sütunları güncelleyin ve bir işlem içinde ağ çağrılarından kaçının.
Yardımcı bir alışkanlık, çakışmalarda yeniden denemektir. İki destek elemanı aynı bileti aynı anda kaydediyorsa, sessizce başarısız olmayın. Çakışmayı tespit edin, en son satırı yeniden yükleyin ve kullanıcıdan değişiklikleri yeniden uygulamasını isteyin.
Sorunları erken fark etmek için deadlock’ları, uzun süreli işlemleri ve çalışmaktan ziyade beklemeye zaman harcayan sorguları izleyin. Yayınlardan sonra yavaş sorgu loglarını rutininizin bir parçası yapın, özellikle yeni ekranlar veya arka plan işleri ekliyorsanız.
Yayına girdikten sonra önemli hale gelen operasyonlar
Yayına girdikten sonra artık sadece sorgu hızını optimize etmiyorsunuz. Kurtarmayı, güvenli değişimi ve öngörülebilir performansı optimize ediyorsunuz.
Sık yapılan bir sonraki adım bir replika eklemektir. Birincil yazmaları işler, bir replika paneller veya raporlar gibi okuma-ağırlıklı sayfaları sunar. Bu, tazelik (freshness) düşüncenizi değiştirir: bazı okumalar saniyelerce gecikebilir, bu yüzden uygulamanız hangi ekranların primerden okunması gerektiğini (ör. "sipariş henüz verildi") bilmelidir.
Yedeklemeler işin yarısıdır. Önemli olan hızlı ve doğru şekilde geri dönebilmenizdir. Düzenli test geri yüklemeleri ayrı bir ortama planlayın, sonra temel doğrulamaları yapın: uygulama bağlanabiliyor mu, kritik tablolar var mı ve önemli sorgular beklenen sonuçları veriyor mu. Ekipler genellikle yanlış şeyi yedeklediklerini veya geri yükleme süresinin kesinti bütçesini çok aştığını geç fark eder.
Güncellemeler de "tıkla ve um" olmaktan çıkar. Bir bakım penceresi planlayın, uyumluluk notlarını okuyun ve üretim verisinin bir kopyasıyla yükseltme yolunu test edin. Küçük sürüm atlamaları bile sorgu planlarını veya indeks ve JSON fonksiyonları etrafındaki davranışı değiştirebilir.
Basit gözlemlenebilirlik (observability) erken fayda sağlar. Yavaş sorgu logları ve toplam sürede en üst sorgular, bağlantı doygunluğu, replikasyon gecikmesi (replika kullanıyorsanız), önbellek isabet oranı ve I/O baskısı ile kilit beklemeleri ve deadlock olayları ile başlayın.
Nasıl seçilir: pratik bir değerlendirme süreci
Kıstıma takıldıysanız, özellik listelerini okumayı bırakıp kendi iş yükünüzle küçük bir deneme yapın. Amaç mükemmel bir kıyaslama değil. Amaç tablolar milyonlara ulaştığında ve yayın döngünüz hızlandığında sürprizlerden kaçınmaktır.
1) Üretime benzeyen küçük bir test inşa edin
Gerçek acınızı temsil eden bir uygulama dilimini seçin: bir veya iki ana tablo, birkaç ekran ve bunların arkasındaki yazma yolları. En önemli sorgularınızı toplayın (liste sayfaları, detay sayfaları ve arka plan işleri). Gerçekçi satır sayıları ekleyin (prototip verinizin en az 100x’i, benzer şekille). İhtiyacınız olduğunu düşündüğünüz indeksleri ekleyin, sonra aynı sorguları aynı filtre ve sıralamalarla çalıştırıp zamanlamaları kaydedin. Yazmalar devam ederken (basit bir insert ve update scripti yeterlidir) tekrarlayın.
Hızlı bir örnek, durumlara göre filtreleyen, isimle arama yapan, son etkinliğe göre sıralayan ve sayfalayan "Müşteriler" listesi olabilir. Bu tek ekran genelde indeksleme ve planlayıcı davranışının iyi mi kötü mü olacağını gösterir.
2) Göçleri gerçek bir yayın gibi prova edin
Veri setinin bir staging kopyasını oluşturun ve gelecek değişiklikleri prova edin: sütun ekleme, tip değiştirme, backfill, indeks ekleme. Ne kadar sürdüğünü, yazmaları engelleyip engellemediğini ve veri zaten değişmişken rollback’in gerçekten ne anlama geldiğini ölçün.
3) Basit bir puan kartı kullanın
Testten sonra her seçeneği gerçek sorgularınız için performans, doğruluk ve güvenlik (kısıtlamalar, işlemler, uç durumlar), göç riski (kilitleme, kesinti, kurtarma seçenekleri), operasyon çabası (yedek/geri yük, replikasyon, izleme) ve ekip rahatlığı açısından puanlayın.
Önümüzdeki 12 ay için riski azaltanı seçin, tek bir mikro-test’i kazananı değil.
Yaygın hatalar ve tuzaklar
En maliyetli veritabanı problemleri genellikle "hızlı kazanımlar" olarak başlar. Her iki veritabanı da bir işlemsel CRUD uygulamasını çalıştırabilir, ama yanlış alışkanlıklar veri ve trafik büyüdüğünde her ikisini de incitir.
Yaygın bir tuzak JSON’u her şey için bir kısayol olarak görmektir. Gerçekten isteğe bağlı veriler için esnek bir "extras" alanı iyidir, ama durum, zaman damgaları ve yabancı anahtarlar gibi çekirdek alanlar gerçek sütun olarak kalmalıdır. Aksi halde yavaş filtreler, garip doğrulamalar ve raporlama öncelik kazandığında zor refaktörler ile karşılaşırsınız.
İndekslemenin kendi tuzağı: ekranda gördüğünüz her filtre için indeks eklemek. İndeksler okumaları hızlandırır ama yazmaları yavaşlatır ve göçleri ağırlaştırır. Kullanıcıların gerçekten kullandığı şeyleri indeksleyin, sonra ölçülmüş yükle doğrulayın.
Göçler büyük tabloları kilitlediğinde acı verir. Büyük bir kolonun yeniden yazılması, varsayılanla NOT NULL eklemek veya büyük bir indeks oluşturmak yazmaları dakika boyunca engelleyebilir. Riskli değişiklikleri adımlara bölün ve uygulamanın sessiz olduğu zamanlarda planlayın.
ORM varsayılanlarına sonsuza kadar güvenmeyin. Bir liste görünümü 1.000 satırdan 10 milyon satıra çıktığında, sorgu planlarını okumalı, eksik indeksleri tespit etmeli ve yavaş join’leri düzeltmelisiniz.
Hızlı uyarı işaretleri: birincil filtre ve sıralama için JSON alanlarına dayanmak, ölçmeden artan indeks sayısı, tek dağıtımda büyük tabloları yeniden yazan göçler ve kararlı sıralama olmadan sayfalama (eksik ve tekrar eden satırlara yol açar).
Karar vermeden önce hızlı kontrol listesi
Bir tarafı seçmeden önce en yoğun ekranlarınız ve yayın süreciniz bazında hızlı bir gerçeklik kontrolü yapın.
- En yoğun ekranlarınız yoğun yük altında hızlı kalabilir mi? En yavaş liste sayfasını gerçek filtreler, sıralama ve sayfalamayla test edin ve indekslerin bu tam sorgulara uyduğunu doğrulayın.
- Güvenli şema değişiklikleri gönderebiliyor musunuz? Önümüzdeki kırılma değişikliği için genişlet-backfill-daralt planını yazın.
- JSON ile sütunlar arasında net bir kuralınız var mı? Hangi JSON anahtarlarının aranabilir veya sıralanabilir olması gerektiğine karar verin.
- Belirli sorgu özelliklerine bağlı mısınız? Upsert davranışını, window fonksiyonlarını, CTE davranışını ve fonksiyonel veya partial indeks ihtiyacını kontrol edin.
- Yayına aldıktan sonra işletmeyi yapabilir misiniz? Yedekten geri yükleyebildiğinizi ispatlayın, yavaş sorguları ölçün ve gecikme ile kilit beklemeleri için baz değerleri alın.
Örnek: basit sipariş takibinden yoğun müşteri portalına
Basit bir müşteri portalı hayal edin: müşteriler giriş yapar, siparişleri görüntüler, faturaları indirir ve destek bileti açar. Birinci hafta neredeyse her işlemsel veritabanı iyi hisseder. Sayfalar hızlı yüklenir ve şema küçüktür.
Birkaç ay sonra büyüme anları ortaya çıkar. Müşteriler "son 30 günde gönderilen, kartla ödenmiş, kısmi iade olan" gibi filtreler ister. Destek hızlı CSV dışa aktarımları ister. Finans bir denetim izi ister: kim fatura durumunu ne zaman ve neye değiştirdi. Sorgu desenleri orijinal ekranlardan daha geniş ve çeşitli hale gelir.
İşte kararın spesifik özellikler ve bunların gerçek yük altındaki davranışı hakkında olması gereken yer burasıdır.
Esnek alanlar eklerseniz (teslim talimatları, özel öznitelikler, bilet meta verileri), JSON desteği önem kazanır çünkü bu alanların içine sorgu yapmanız gerekebilir. Ekip olarak JSON yollarını indeksleyip şekilleri doğrulayıp JSON büyüdükçe performansı öngörülebilir tutup tutamayacağınıza dürüst olun.
Raporlama başka bir baskı noktasıdır. Siparişleri, faturaları, ödemeleri ve biletleri çok sayıda filtreyle join ettiğiniz an bileşik indeksler, sorgu planlaması ve indeksleri kesinti olmadan evrimleştirmenin kolaylığı önem kazanır. Göçler de "Cuma scripti çalıştırma" olmaktan çıkar; küçük bir şema değişikliği milyonlarca satırı etkileyebilir.
Pratik bir yol: altı ay içinde beklediğiniz beş gerçek ekranı ve dışa aktarmayı yazın, audit history tablolarını erkenden ekleyin, en yavaş sorgularınızı gerçekçi veri boyutuyla benchmark edin (hello-world CRUD değil) ve ekip kurallarını JSON kullanımı, indeksleme ve göçler için belgeleyin.
Eğer her katmanı elle inşa etmeden hızlı ilerlemek istiyorsanız, AppMaster (appmaster.io) tek bir görsel modelden üretim hazır back-end’ler, web uygulamaları ve native mobil uygulamalar oluşturabilir. Ayrıca ekranları, filtreleri ve iş süreçlerini gerçek sorgu iş yükleri olarak erken ele almanızı teşvik eder; bu, indeksleme ve göç risklerini üretime gelmeden önce yakalamanıza yardımcı olur.
SSS
Gerçek iş yükünüzü yazın: en yoğun liste ekranlarınız, filtreleriniz, sıralamalarınız ve yoğun yazma yollarınız. Her ikisi de CRUD’u iyi çalıştırabilir, ama daha güvenli seçim, isim tanıdık geldiği için değil; önümüzdeki yıl boyunca indeksleme, göçler ve sorgulama alışkanlıklarınıza en uygun olanıdır.
Sayfa derinleştikçe liste sayfaları yavaşlıyorsa, muhtemelen OFFSET taramalarının maliyetini ödüyorsunuz. Kaydetme işlemi yoğun saatlerde takılıyorsa, kilitleşme veya uzun işlemler (long transactions) olabilir. Yayınlar artık backfill’ler ve büyük indeksler içeriyorsa, göçler sadece bir şema değişikliği değil, güvenilirlik sorunudur.
Her önemli ekran sorgusu için varsayılan olarak tek bir bileşik (composite) indeks oluşturun; en tutarlı filtreleri öne, sıralama sütununu sona koyun. Örneğin çok kiracılı listeler için (tenant_id, status, created_at) genellikle filtreleme ve sıralamayı ekstra tarama olmadan destekler.
OFFSET ile sayfalama yüksek sayfalara gidildikçe yavaşlar çünkü veritabanı önceki satırlardan geçmek zorunda kalır. Bunun yerine anahtar-set (keyset) sayfalama kullanın: son görülen created_at ve id gibi değerleri verip “ondan daha eski 20” isteyin; bu, performansı daha dengeli tutar ve yeni satırlar eklenince tekrarlar veya boşlukları azaltır.
İhtiyacınız olmayan her filtre için indeks eklemeyin. Bir indeksi yalnızca hangi ekranın veya API çağrısının ona ihtiyaç duyduğunu isimlendirebiliyorsanız ekleyin. Örtüşen çok fazla indeks, her insert ve update’i yavaşlatır ve yoğun yazma dönemlerinde uygulamanın “rastgele” yavaşlamasına neden olur.
Genişlet, doldur (backfill), daralt şeklini kullanın: uyumlu yeni yapılar ekleyin, küçük partilerle backfill yapın, kısıtlamalarla doğrulayın, sonra eski yolu yalnızca okuma/yazma geçtiyse kaldırın. Bu büyük tablolar ve sürekli trafik altında yayınları daha güvenli kılar.
JSON’u genellikle görüntülenen veya hata ayıklama için saklanan yük benzeri verilerde tutun; eğer düzenli olarak filtreliyor, sıralıyor veya raporluyorsanız alanları gerçek sütunlara taşıyın. Bu, JSON ağırlıklı sorguların yavaşlamasını ve kısıtlama (constraint) uygulanmasını zorlaştırmaktan kaçınır.
Yeniden denemelerin normal olduğu durumlarda upsert kullanmak şarttır (mobil ağlar, background joblar, zaman aşımı). PostgreSQL’de INSERT ... ON CONFLICT, MariaDB’de INSERT ... ON DUPLICATE KEY UPDATE kullanılır; her iki durumda da tekrarların kayıt oluşturmasını engelleyecek şekilde benzersiz anahtarları dikkatli tanımlayın.
İşlemleri kısa tutun, bir işlem (transaction) açıkken ağ çağrılarından kaçının ve herkesin güncellediği “sıcak satırlardan” (hot rows) uzak durun. Çakışma olduğunda yeniden denemeyi veya çakışmayı kullanıcıya net biçimde göstermeyi alışkanlık haline getirin; böylece düzenlemeler sessizce kaybolmaz.
Evet, eğer okuma-ağırlıklı sayfalar biraz gecikmeyi tolere edebiliyorsa. Kritik "hemen değişti" okumalarını (ör. sipariş yerleştirildikten hemen sonra) primerde tutun ve replikasyon gecikmesini izleyin, böylece kullanıcıya yanıltıcı derecede eski veri göstermemiş olursunuz.


