- Konu sahibi
- #1
Veritabanı normalizasyonu neden kullanılır?
Veritabanı normalizasyonu; aynı bilginin gereksiz tekrarını azaltmak, ekleme-güncelleme-silme sırasında oluşabilecek tutarsızlıkları önlemek ve tabloları anlamlı sorumluluklara ayırmak için kullanılır. Amaç her şeyi mümkün olduğunca çok tabloya bölmek değil, verinin doğru yerde ve yalnızca gerekli tekrarlarla tutulmasını sağlamaktır.
Normalizasyon nasıl çalışır?
Normalizasyon, tabloların ve aralarındaki bağımlılıkların belirli kurallara göre düzenlenmesidir. Örneğin bir sipariş tablosunda müşteri adı, müşteri e-postası ve ürün adı tekrar tekrar tutulursa aynı bilgi birçok satıra dağılır. Müşterinin e-postası değiştiğinde ilgili tüm satırların güncellenmesi gerekir. Bir satır unutulursa veritabanında aynı müşteri için farklı e-posta değerleri oluşabilir.
Bu bilgileri müşteri, sipariş, ürün ve sipariş kalemi gibi ayrı tablolara ayırmak tekrarları azaltır. Tablolar birincil anahtar ve yabancı anahtarlarla ilişkilendirilir. Böylece müşteri bilgisi müşteri tablosunda, ürün bilgisi ürün tablosunda, sipariş ile ürün arasındaki miktar bilgisi ise sipariş kalemi tablosunda tutulur.
Normalizasyon genellikle şu hedeflerle açıklanır:
- Her hücrede tek ve bölünemez bir değer tutmak; örneğin
urun1,urun2gibi virgülle ayrılmış listeler kullanmamak. - Bir tablodaki her alanın o tablonun anahtarını açıklamasını sağlamak.
- Bir alanın, anahtarın yalnızca bir bölümüne veya başka bir anahtar olmayan alana gereksiz biçimde bağlı olmasını önlemek.
- Aynı bilginin farklı satırlarda çelişkili tutulmasını engellemek.
Somut örnek: sipariş verisi
Başlangıçta aşağıdaki gibi tek bir tablo olduğunu varsayalım:
Kod:
Siparis
id | musteri_adi | musteri_email | urun_adi | adet | birim_fiyat
Bir siparişte birden fazla ürün varsa müşteri ve sipariş bilgileri her ürün satırında tekrarlanır. Ayrıca aynı ürünün fiyatı sipariş anında korunacaksa güncel ürün fiyatıyla siparişteki satış fiyatını birbirine karıştırmamak gerekir.
Daha düzenli bir tasarım şu şekilde olabilir:
Kod:
Musteri(id, ad, email)
Siparis(id, musteri_id, siparis_tarihi)
Urun(id, ad)
SiparisKalemi(id, siparis_id, urun_id, adet, birim_fiyat)
Burada
Siparis.musteri_id, müşteriyi; SiparisKalemi.siparis_id siparişi; SiparisKalemi.urun_id ise ürünü gösterir. Sipariş kalemindeki birim_fiyat özellikle sipariş sırasında uygulanan fiyatı temsil ediyorsa burada bulunması doğrudur; çünkü bu değer ürünün bugün geçerli fiyatından farklı olabilir.Normal formları örneğe uygulama
| Kontrol | Sorun örneği | Düzenleme |
|---|---|---|
| Birinci normal form | Aynı sütunda ürün kimlik listesi | Her kalemi ayrı satır yapın |
| İkinci normal form | Birleşik anahtarın yalnız ürün bölümüne bağlı ürün adı | Ürün bilgilerini ürün tablosuna ayırın |
| Üçüncü normal form | Siparişte müşteri kimliğine bağlı güncel müşteri e-postası | Güncel e-postayı müşteri tablosunda tutun |
Bunlar başlangıç örnekleridir; tam normal form değerlendirmesi aday anahtarlar ve iş kurallarının belirlediği işlevsel bağımlılıklar üzerinden yapılır. Otomatik id sütunu eklemek bağımlılık sorununu tek başına gidermez. Faturadaki tarihsel adres veya satış anındaki fiyat ayrı bir iş gerçeğidir; güncel müşteri/ürün kaydını kopyalamakla aynı amaçta değildir.
Uygularken izlenecek yol
- Saklanacak varlıkları belirleyin: müşteri, sipariş, ürün ve benzeri kavramları ayrı ayrı listeleyin.
- Her tabloya değişmeyen birincil anahtar verin. İlişkili kayıtlar için yabancı anahtar kullanın.
- Tek bir alanda liste, tekrar eden sütun veya iç içe metin tutmayın.
urun1,urun2gibi sütunlar yerine ayrı sipariş kalemi satırları oluşturun. - Her alanın hangi varlığa ait olduğunu kontrol edin. Müşteri e-postası müşteri tablosuna, sipariş tarihi sipariş tablosuna ait olmalıdır.
- Ekleme, güncelleme ve silme senaryolarını deneyin: yeni müşteriyi sipariş vermeden ekleyebiliyor musunuz, e-posta değişince tek kayıt güncelleniyor mu, son sipariş silinince müşteri bilgisi yanlışlıkla kayboluyor mu?
- Gereken bilgiyi tabloları birleştiren sorguyla alın. Normalleştirilmiş yapı, sorgu yazmayı engellemez; ilişkileri açık hale getirir.
Bu kontroller sonucunda bir müşteri bilgisi tek yerde güncelleniyor, yeni bir ürünü henüz sipariş edilmeden ekleyebiliyor ve bir sipariş silindiğinde ürün kaydı yanlışlıkla silinmiyorsa tasarım temel amacına ulaşıyor demektir.
Normalizasyonu ne kadar uygulamalı?
Normalizasyon veri doğruluğu ve bakım kolaylığı öncelikliyse güçlü bir başlangıç tercihidir. Ancak raporlama veya çok sık okunan sorgularda bazı değerleri bilerek tekrarlamak performans ya da kullanım kolaylığı sağlayabilir. Bu işlem denormalizasyon olarak adlandırılır ve rastgele yapılmamalıdır. Önce normal bir model kurulur; tekrar edilen alanın nasıl güncelleneceği, hangi kaynağın doğru kabul edileceği ve tutarsızlığın nasıl önleneceği açıkça belirlenir.
En sık hata, yalnızca tablo sayısını artırmayı normalizasyon sanmaktır. Anlamsız bölme sorguları zorlaştırabilir. Diğer hata ise tarihsel olarak değişmemesi gereken bilgiyi güncel tablodan hesaplamaktır. Örneğin eski siparişin satış fiyatı korunacaksa sipariş kaleminde ayrıca saklanmalıdır. Virgülle ayrılmış kimlik listeleri ve aynı anlamı taşıyan kopya sütunlar da ileride veri bütünlüğü sorunlarına yol açar.
Sık sorulan sorular
Normalizasyon her zaman performansı artırır mı?
Hayır. Tekrarlı veriyi azaltıp tutarlılığı artırır; ancak bazı sorgular daha fazla tablo birleştirmesi gerektirebilir. Performans sorunu ölçülerek ve veri bütünlüğü korunarak çözülmelidir.
Hangi normalizasyon seviyesinde durmalıyım?
İlk hedef, her alanın tek anlam taşıdığı ve güncelleme anomalilerinin giderildiği tutarlı bir tasarım kurmaktır. Daha ileri ayırma sorguları gereksiz zorlaştırıyorsa kullanım senaryosunu ve bakım maliyetini değerlendirerek durabilirsiniz.
Normalizasyon veritabanı kısıtlamalarının yerini tutar mı?
Hayır. Birincil anahtar, yabancı anahtar,
UNIQUE, NOT NULL ve uygun CHECK kısıtlamalarıyla birlikte kullanılmalıdır. Normalizasyon yapısı düzenler; kısıtlamalar geçersiz verinin yazılmasını engeller.