• 30.10.2026 19:05:57
  • İbrahim Gökyar

Çalışan geliştiriciler için MongoDB'de şema tasarımı prensipleri, performans stratejileri ve ilişkisel veritabanlarından geçiş adımları. Gerçek dünya örnekleri ve kodlarla uygulanabilir rehber.

MongoDB ile Şema Tasarımı: Esnek NoSQL Modelleri ve Geçiş Rehberi

NoSQL veri tabanları özellikle ölçeklenebilirlik ve esneklik sağladıkları için modern web uygulamalarında sıkça tercih ediliyor. Bu makalede MongoDB özelinde şema tasarımına odaklanacağız: hangi durumlarda embed (gömme) kullanmalı, hangi durumlarda referans tercih edilmeli, sorgu performansını nasıl iyileştirebilirsiniz ve ilişkisel veritabanlarından (RDBMS) geçişte dikkat edilmesi gereken pratik noktalar nelerdir. Kod örnekleri Node.js ve Mongoose üzerinden verilecek; ama ana prensipler başka diller ve sürücüler için de geçerlidir.

Neden şema tasarımı NoSQL'de farklıdır?

Relational modellerde normalizasyon ve tablo ilişkileri ön plandadır; veriyi tekrar etmemek için join'ler kullanılır. NoSQL (özellikle belge tabanlı olan MongoDB) ise uygulama sorgu kalıplarına göre veriyi şekillendirmeyi teşvik eder. Ama bu, şema olmadığı anlamına gelmez—tercih edilen şema, uygulamanızın erişim desenlerine göre optimize edilmelidir.

Örneğin okuma ağırlıklı bir uygulamada sık kullanılan verileri tek bir belge içinde gömmek (embed) gereksiz join ihtiyacını kaldırır ve I/O azaltır. Yazma ve güncelleme rekabetinin yüksek olduğu senaryolarda ise referans tabanlı bir model tercih etmek veri tutarlılığı ve güncelleme maliyetlerini düşürebilir.

Embed vs Referans: Karar ağacı

Bir tasarım sorunu çıktığında sorulması gereken temel sorular şunlardır: Veri birlikte mi okunuyor? Veri sık sık güncelleniyor mu? Alt nesnelerin bağımsız yaşam döngüsü var mı? Bu üç sorunun cevabı, gömme mi yoksa referans mı tercih edeceğinizi belirler.

Pratik bir karar ağacı şöyle özetlenebilir:

  • Birlikte sık okunuyorsa ve boyut makul seviyedeyse: embed.
  • Ayrı ayrı güncelleniyorsa veya yaşam döngüleri bağımsızsa: referans (ObjectId ile ilişkilendirme).
  • Belge boyutu MongoDB limitlerine (16MB) yaklaşacaksa: referans.

Örnek: Bir e-ticaret uygulamasında sipariş ve sipariş satırları. Eğer sipariş oluşturulurken satırlar nadiren güncellenecekse embed uygun. Ancak ürün bilgileri sık güncelleniyorsa ve aynı ürün birçok siparişte tekrar kullanılıyorsa ürünler referansla tutulmalı.

Gerçek dünya örneği: Blog uygulaması

Basit bir blog/yorum sistemi düşünelim. Yazar, gönderiler ve yorumlar var. Yorumlar genelde gönderiyle birlikte okunur ama çok sayıda yorum olabilir. Burada iki yaygın model şunlardır:

  • Yorumları gömmek: Hızlı okuma, tek belgede tüm bilgi. Ancak yorum sayısı çok artarsa belge şişer.
  • Yorumları ayrı koleksiyonda tutup gönderiye referans vermek: Yorumlar bağımsız olarak sayfalanabilir ve silinebilir.

Aşağıda Mongoose örneği ile her iki yaklaşımın kısa bir gösterimi var.

<!-- Gömmek (embed) -->
const PostSchema = new mongoose.Schema({
  title: String,
  body: String,
  comments: [{ author: String, text: String, createdAt: Date }]
});

<!-- Referans (separate collection) -->
const PostSchema = new mongoose.Schema({ title: String, body: String });
const CommentSchema = new mongoose.Schema({ postId: mongoose.ObjectId, author: String, text: String, createdAt: Date });

Sorgu performansı ve indeksleme stratejileri

İyi bir şema tasarımı indeksleme ile tamamlanmalıdır. MongoDB'de uygun indeksler olmadan, belgesel esneklik performans kaybına yol açabilir. En sık kullanılan sorgu alanlarını, range filtrelerini ve sort kriterlerini önceden belirleyip ona göre indeks oluşturun.

Compound indeksler, sık kullanılan birden fazla alanı içeren sorgularda fayda sağlar. Ayrıca text indeksleri arama işlevselliği için uygundur. Ancak indeks sayısını gereksiz artırmak yazma maliyetini yükseltir; dengeyi uygulama ihtiyaçlarına göre kurun.

// Örnek Mongoose indeks tanımı
PostSchema.index({ authorId: 1, createdAt: -1 });
// Text arama için:
PostSchema.index({ title: 'text', body: 'text' });

İlişkisel sistemlerden geçiş: adım adım pratik yaklaşım

RDBMS'den MongoDB'ye geçiş planlarken aşağıdaki adımları takip etmek genellikle başarılı sonuç verir:

  • Uygulamanın sorgu profillerini toplayın: hangi sorgular en çok çalışıyor, hangi alanlar sıklıkla filtreleniyor veya sort ediliyor?
  • Bu sorgulara göre denormalize edilecek verileri belirleyin. Yani hangi ilişkilerin gömülmesinin performans getireceğini seçin.
  • Küçük bir hizmet veya API'yi MongoDB'ye geçirip gerçek yük altında test edin. Bu, büyük göçler öncesi riskleri azaltır.
  • Veri tutarlılığı gereksinimlerini yeniden değerlendirip gerekiyorsa iki fazlı commit benzeri mekanizmalardan kaçınmak için uygulama seviyesinde kompansasyon mantığı yazın.

Özellikle çok sayıda join kullanan sorgular varsa, MongoDB'de aggregation pipeline veya $lookup operatörü kullanılabilir. Ancak $lookup'un klasik RDBMS join performansını vermediğini ve dikkatli kullanılması gerektiğini unutmayın.

// Basit bir $lookup örneği
db.orders.aggregate([
  { $match: { status: 'paid' } },
  { $lookup: { from: 'customers', localField: 'customerId', foreignField: '_id', as: 'customer' } },
  { $unwind: '$customer' }
]);

Pratik ipuçları: tutarlılık, hata yönetimi ve göç süreci

MongoDB, ACID garantilerini tek belge genişliğinde sağlar; çok belgeyi içeren işlemler için transaction desteği bulunmaktadır (özellikle 4.0+ sürümlerle). Ancak yüksek performans gerektiren sistemlerde transaction kullanımı maliyetli olabilir. Bu nedenle mümkün olduğunca tek belge sınırları içinde kalmak faydalıdır.

Geçiş sürecinde veri dönüşümü (ETL) hataları kaçınılmaz olabilir. İyi bir yaklaşım, her kaydı idempotent şekilde dönüştürecek, hataları loglayıp yeniden işleyebilecek bir pipeline kurmaktır. Parçalı geçiş (sadece bazı servisleri veya bazı veri tiplerini taşımak) riski azaltır ve rollback imkânı sağlar.

Sık Sorulan Sorular

1) MongoDB her senaryoda ilişkisel veritabanlarını ortadan kaldırır mı?

Hayır. MongoDB birçok senaryoda avantaj sağlar ama güçlü ilişkiler, sık ve karmaşık join'ler veya ağır transaction gerektiren finansal uygulamalar gibi durumlarda ilişkisel veritabanları daha uygun olabilir. Doğru araç, uygulamanın ihtiyaçlarına göre seçilmelidir.

2) Çok büyük belgeler sorun yaratır mı?

Evet. MongoDB'de bir belge için 16MB gibi pratik limitler vardır ve çok büyük belgeler performans, ağ taşımacılığı ve bellek kullanımında sorun çıkarır. Büyük koleksiyonlar için referans modelini veya dosya depolama (GridFS ya da obje depolama servisleri) kullanmayı değerlendirin.

3) Denormalizasyon veri tutarlılığını nasıl etkiler?

Denormalizasyon, veri tekrarına yol açtığı için güncellemelerde tutarlılık sorunları doğurabilir. Bu yüzden uygulama seviyesinde güncelleme mantığı (örn. transactional workflow, compensating operations) veya arka plan senkronizasyon süreçleri kurulmalıdır. MongoDB'nin multi-document transaction desteği bazı durumlarda yardımcı olur ancak performans maliyetini göz önünde bulundurun.

İlgili Eğitim

Sonuç

MongoDB ile şema tasarımı, uygulamanızın sorgu kalıplarını anlamakla başlar. Embed ve referans arasında bilinçli tercihler yapmak, doğru indeksleme stratejileri uygulamak ve geçiş sürecinde adım adım ilerlemek uzun vadede performans ve bakım kolaylığı sağlar. İlişkisel sistemlere alışkın geliştiriciler için NoSQL’e geçiş zihinsel bir değişim gerektirir: veriyi uygulama gözünden modellemek ve okuma/yazma ayak izini minimize etmek başarının anahtarıdır.