Bir haber sitesinin hızı, çoğu zaman veritabanı katmanında kazanılır ya da kaybedilir. Sayfa şablonu ne kadar yalın olursa olsun, arka planda yavaş çalışan bir sorgu tüm deneyimi geciktirir. Bu rehberde hızlı bir veritabanı yapısını planlamaktan indeksleme, önbellek ve ölçeklemeye kadar sahadan pratik adımları anlatıyoruz.
Bu yazı, SEO uyumlu haber yazılımı rehberinin bir alt başlığıdır. Performans bütününün diğer parçaları için önbellek ve görsel optimizasyonu yazılarına da göz atabilirsiniz.
Hızlı Veritabanı Katmanı Neden Önemli?
Kullanıcı bir habere tıkladığında sunucu; içeriği, ilgili haberleri, yorum sayısını ve menüyü genellikle veritabanından okur. Bu okumalar milisaniyeler içinde tamamlanmazsa, ilk bayta kadar geçen süre (TTFB) uzar. Yavaş TTFB hem kullanıcı deneyimini hem de tarama bütçesini olumsuz etkiler.
Trafik dalgalı olduğunda sorun büyür. Bir haberin viral olması, aynı anda binlerce isteğin aynı sorguları çalıştırması demektir. Katman iyi tasarlanmamışsa veritabanı darboğaza döner ve site çöker. Amaç, hem ortalama yükte düşük gecikme hem de ani yükte kararlılık sağlamaktır.
Bir başka önemli nokta, veritabanının web sunucusuyla paylaştığı kaynaklardır. Uygulama sunucusu bir isteği işlerken veritabanı yavaş cevap veriyorsa, o istek için ayrılan iş parçacığı (thread) bekler; bekleyen istekler birikince görünürde bol kaynaklı bir sunucu bile yanıt veremez hale gelir. Yani veritabanı gecikmesi, doğrudan eş zamanlı işleyebileceğiniz istek sayısını sınırlar.
Doğru Veritabanı Modelini Seçmek
Çoğu haber sitesi için ilişkisel bir veritabanı (PostgreSQL veya MySQL/MariaDB) doğru başlangıçtır. Yazılar, kategoriler, yazarlar ve yorumlar net ilişkiler içerir; ilişkisel modeller bu tür yapılandırılmış veriyi tutarlı biçimde saklar. NoSQL çözümleri belirli iş yükleri için değerlidir ama her problem için gerekli değildir.
| İhtiyaç | Uygun yaklaşım |
|---|---|
| Yapılandırılmış içerik, ilişkiler, işlemler | İlişkisel (PostgreSQL, MySQL, MariaDB) |
| Anahtar-değer önbellek, oturum, sayaç | Bellek içi depo (ör. Redis) |
| Tam metin arama, gelişmiş sıralama | Arama motoru (ör. bir arama indeksleyici) |
| Çok büyük, şemasız günlük/analitik | Belge veya sütun tabanlı depo |
Şema Tasarımı ve Normalizasyon
Hız, çoğu zaman iyi bir şemayla başlar. Normalizasyon veri tekrarını azaltır ve tutarlılığı korur. Ancak aşırı normalizasyon, her sayfa için çok sayıda birleştirme (JOIN) gerektirebilir. Uygulamada dengeli bir tasarım hedeflenir: temel veri normalize edilir, sık okunan bazı alanlar bilinçli olarak denormalize edilebilir.
Her sütun için mümkün olan en dar ve doğru veri tipini seçin. Tarih için metin yerine tarih/zaman tipi, kısa durumlar için tam sayı veya enum kullanmak hem yeri hem karşılaştırma maliyetini azaltır. Birincil anahtarları küçük ve değişmez tutun.
Şemayı tasarlarken erişim desenini, yani veriyi nasıl okuyacağınızı düşünün. Tablolar sadece verinin "doğru" halini değil, sayfaların ihtiyaç duyduğu okumaları da kolaylaştıracak şekilde kurulmalıdır. Örneğin bir haberin ana sayfada gösterilecek özet, başlık ve kapak alanı tek bir satırda birlikte durursa, liste sayfaları tek sorguyla dolar. Erişim desenini göz ardı eden "kağıt üzerinde temiz" bir şema, üretimde çok sayıda gereksiz birleştirmeye yol açabilir.
- Sık filtrelenen alanları (yayın tarihi, kategori, durum) baştan planlayın.
- Büyük metin ve medya verisini ayrı tablolara ya da nesne depolamaya taşıyın.
- Sayaçlar gibi çok yazılan alanları ana satırdan ayırarak kilitlenmeyi azaltın.
- Denormalizasyonu yalnızca ölçülebilir bir kazanç için ve bilinçli yapın.
İndeksleme: Sorguların Temeli
İndeks, veritabanının bir değeri tüm tabloyu taramadan bulmasını sağlar. Doğru indeks, saniyeler süren bir sorguyu milisaniyeye indirebilir. Genel kural: WHERE, JOIN ve ORDER BY ifadelerinde kullanılan sütunlar indekslenmeye adaydır.
Bileşik (çok sütunlu) indekslerde sütun sırası önemlidir. Örneğin bir kategori içindeki haberleri tarihe göre sıralıyorsanız, kategori ve tarih sütunlarını birlikte içeren bir indeks hem filtreleme hem sıralamayı tek geçişte karşılayabilir.
-- Kategoriye gore filtreleyip tarihe gore siralayan sayfalama
CREATE INDEX idx_haber_kategori_tarih
ON haberler (kategori_id, yayin_tarihi DESC);
SELECT id, baslik, ozet, yayin_tarihi
FROM haberler
WHERE kategori_id = 12
AND durum = 'yayinda'
ORDER BY yayin_tarihi DESC
LIMIT 20;Sorgu Optimizasyonu ve Yürütme Planı
Yavaş bir sayfanın arkasında çoğu zaman tek bir problemli sorgu vardır. EXPLAIN (PostgreSQL'de EXPLAIN ANALYZE) komutu, veritabanının bir sorguyu nasıl çalıştırdığını gösterir: indeks mi kullanıyor, yoksa tüm tabloyu mu tarıyor?
-- Sorgunun gercek yurutme planini ve suresini gormek
EXPLAIN ANALYZE
SELECT id, baslik
FROM haberler
WHERE kategori_id = 12
ORDER BY yayin_tarihi DESC
LIMIT 20;- "Seq Scan" / tam tablo taraması görüyorsanız, uygun indeks eksik olabilir.
- SELECT * yerine yalnızca gereken sütunları seçin.
- N+1 sorgu tuzağından kaçının: listelerde her satır için ayrı sorgu atmayın.
- Sayfalamada çok büyük OFFSET yerine anahtar tabanlı sayfalama (keyset) tercih edin.
Sorgu yazarken planlayıcıya (query planner) yardım etmeyi de unutmayın. Bir sütun üzerinde fonksiyon çalıştırmak (örneğin tarihin yılını hesaplamak) çoğu zaman o sütundaki indeksi kullanılamaz hale getirir; bunun yerine sorguyu, koşulu ham sütuna uygulayacak biçimde yeniden yazmak gerekir. Küçük görünen bu ayrıntılar, tam tablo taraması ile indeksli erişim arasındaki farkı belirler.
Bağlantı Havuzu (Connection Pooling)
Her veritabanı bağlantısı kaynak tüketir. Her istek için yeni bağlantı açıp kapatmak, hem gecikme ekler hem de yoğun trafikte sunucuyu bağlantı sayısında boğar. Bağlantı havuzu, önceden açılmış bir grup bağlantıyı yeniden kullanarak bu maliyeti düşürür.
Havuz boyutunu gerçekçi tutun. Çok büyük bir havuz, veritabanını aynı anda çok fazla istekle meşgul ederek ters etki yapabilir. Uygun boyut; çekirdek sayısı, disk hızı ve sorgu profiline göre ölçümle belirlenir. PostgreSQL gibi sistemlerde harici bir havuzlayıcı da kullanılabilir.
| Belirti | Olası neden | Yön |
|---|---|---|
| Ani yükte "too many connections" | Havuz yok veya çok büyük | Havuz kur, üst sınırı ölç |
| Boşta yüksek gecikme | Bağlantı kurulum maliyeti | Kalıcı havuz kullan |
| Veritabanı CPU'su hep yüksek | Fazla eşzamanlı sorgu | Havuzu daralt, sorguları hızlandır |
Yazma Yükü ve İşlemler (Transaction)
Okuma tarafını hızlandırmak kadar, yazma tarafını kontrol altında tutmak da önemlidir. Her yorum, her görüntülenme sayacı ve her yeni haber bir yazma işlemidir. İşlemleri (transaction) olabildiğince kısa tutun: uzun süre açık kalan bir işlem, ilgili satırları kilitleyerek başka isteklerin beklemesine yol açar.
Çok sık artan sayaçlar (görüntülenme, beğeni) veritabanı için zorlayıcıdır çünkü aynı satıra yoğun eşzamanlı yazma yaratır. Bu tür değerleri önce bellekte biriktirip belirli aralıklarla toplu olarak yazmak, kilit çekişmesini ciddi biçimde azaltır. Toplu içe aktarımlarda da tek tek yerine gruplu (batch) ekleme kullanın.
Önbellek Katmanı
En hızlı sorgu, hiç çalıştırılmayan sorgudur. Sık okunan ve nadiren değişen veriler (ana sayfa listeleri, kategori sayfaları, popüler haberler) bir önbellekte tutulabilir. Böylece aynı veri her istekte veritabanından yeniden hesaplanmaz.
Önbellekte kritik konu geçerliliktir: veri değiştiğinde ilgili önbellek girdisini temizlemek (invalidation) gerekir. Bir haber güncellendiğinde onu içeren liste ve sayfa önbellekleri tazelenmelidir. Ayrıntılar için önbellek nasıl çalışır yazısına bakın.
- Uygulama içi önbellek: bellekte küçük, sık kullanılan veriler.
- Paylaşılan önbellek deposu: birden çok sunucu arasında ortak veri (ör. Redis).
- HTTP / kenar önbelleği: tüm sayfa veya parçaların CDN düzeyinde önbelleği.
- Malzeme görünümleri (materialized view): ağır toplama sorgularının önceden hesaplanması.
Okuma Replikaları ve Ölçekleme
Haber siteleri ağırlıklı olarak okuma yapar; yazma (yeni haber, yorum) oran olarak azdır. Bu yapı, okuma replikalarıyla ölçeklemeye uygundur: yazmalar ana sunucuya (primary) gider, okumalar bir veya daha çok replikaya dağıtılır.
Replikasyonda çoğu kurulum eşzamansızdır; yani replikada verinin görünmesi çok kısa bir gecikme alabilir. Yeni yazılan veriyi hemen aynı kullanıcıya göstermeniz gereken durumlarda o okumayı primary'den yapmak gerekir.
Donanım, Depolama ve Bellek
Veritabanı, sıcak veriyi (aktif olarak okunan tablolar ve indeksler) bellekte tutabildiğinde en hızlı çalışır. Yeterli RAM, disk okumalarını azaltır. Depolamada dönen diskler yerine SSD/NVMe kullanmak, rastgele okuma performansını belirgin biçimde artırır.
- Çalışma setinin (sık erişilen veri + indeks) bellekte kalmasını hedefleyin.
- SSD/NVMe depolama, veritabanı iş yükleri için dönen disklere göre çok daha uygundur.
- Veritabanı ile web sunucusunu ayrı süreçlerde/kaynaklarda tutmak öngörülebilirlik sağlar.
- Yedekleri düzenli alın ve geri yükleme sürecini gerçekten test edin.
İzleme, Bakım ve Sürdürülebilirlik
Ölçmediğiniz şeyi iyileştiremezsiniz. Sorgu süreleri, bağlantı sayısı, önbellek isabet oranı ve disk kullanımı gibi metrikleri sürekli izleyin. Böylece bir yavaşlamanın nereden geldiğini tahminle değil veriyle görürsünüz.
- Yavaş sorgu günlüğünü açık tutun ve düzenli inceleyin.
- İstatistikleri güncel tutun; planlayıcının doğru karar vermesi buna bağlıdır.
- Kullanılmayan indeksleri ve şişen tabloları periyodik olarak temizleyin.
- Şema değişikliklerini yoğun saatlerin dışında ve önce test ortamında uygulayın.
Haber Siteleri İçin Pratik Notlar
Haber akışı sürekli değiştiği için ana sayfa ve kategori listeleri en çok okunan sorgulardır; bunları önbelleğe almak büyük fark yaratır. Dış RSS ve XML veri kaynaklarını işlerken toplu (batch) yazma kullanın; her öğe için ayrı işlem açmak yerine gruplayın.
Trafiği manşetten gelen bir haber patlamasında, o tek sayfanın sorgusu tüm sistemin darboğazı olabilir. Popüler içeriği agresif önbelleğe almak ve okuma replikalarına dağıtmak, bu ani yükleri sönümler.
Arşiv de göz ardı edilmemelidir. Yıllar içinde biriken haberler tabloyu büyütür ve eski, nadiren okunan içerik güncel sorguları yavaşlatabilir. Sık erişilen güncel veriyi sıcak, eski veriyi ayrı ele almak; gerekirse tarih temelli bölümleme (partitioning) kullanmak, tablolar büyüdükçe performansı korumanın etkili yollarındandır. Kısacası hızlı bir veritabanı katmanı, tek seferlik bir kurulum değil, ölçüme dayalı sürekli bir bakım işidir.