Veri tabanı tasarımı, sadece tablolar oluşturup içine veri doldurmak değil; verinin en verimli, güvenli ve performanslı şekilde saklanmasını sağlama sanatıdır. Bu sanatın merkezinde ise Normalizasyon yer alır.
Normalizasyon, bir ilişkisel veri tabanı (RDBMS) tasarımında verileri mantıksal alt kümelere ayırarak veri tekrarını (redundancy) en aza indirme ve veri tutarlılığını (integrity) en üst düzeye çıkarma işlemidir. MSSQL Server gibi sistemlerde, verinin karmaşadan arındırılıp belirli kurallar çerçevesinde tablolara dağıtılması sürecidir.
Bu sürecin temel amacı, veri tabanında meydana gelebilecek “anomalileri” (ekleme, silme ve güncelleme sırasında oluşan hatalar) engellemek ve depolama alanını optimize etmektir.
Normalizasyonun uygulanmadığı bir sistem, “Insert”, “Update” ve “Delete” işlemleri sırasında ciddi mantıksal hatalara gebedir. Normalizasyonun sağladığı temel avantajlar şunlardır:
- Veri Tekrarını Önler: Aynı bilginin birden fazla tabloda veya satırda gereksiz yere tutulmasını engeller.
- Veri Tutarlılığı Sağlar: Bir veri güncellendiğinde, bu verinin bağlı olduğu tüm noktaların otomatik olarak doğru kalmasını garantiler.
- Depolama Tasarrufu: Gereksiz tekrarlar kalktığı için disk alanı daha verimli kullanılır.
- Sorgu Performansı (Bazen): Tablolar küçüldüğü için indeksleme daha verimli çalışır (ancak aşırı normalizasyon çok fazla JOIN gerektirebilir).
- Esneklik: Veri yapısında yapılacak bir değişiklik, sadece ilgili küçük tabloyu etkiler.
Normalizasyon süreci Normal Formlar (NF) olarak adlandırılan aşamalardan oluşur. En yaygın kullanılan ilk üç formu bir örnek üzerinden inceleyelim:
Kesinlikle haklısın, bir önceki aşamada 1NF’de veriyi atomik hale getirirken oluşan satır çoklamasını, 2NF tablosuna taşırken Yunus Yücel’in ikinci numarasını (0212) “yutmuşuz”. Veri tutarlılığı açısından bu büyük bir hata olurdu; çünkü normalizasyonun amacı veriyi silmek değil, daha düzenli saklamaktır.
Hataları düzelterek, akışı mantıksal bir silsileye oturtan makale formatındaki nihai hali aşağıdadır:
Başlangıç Noktası: Normalize Edilmemiş (Unnormalized) Yapı
Aşağıdaki tabloda “Telefonlar” kolonu birden fazla veri içermekte ve tüm bilgiler tek bir yerde toplanmaktadır.
| SiparisID | MusteriAd | Telefonlar | UrunID | UrunAd | BirimFiyat | IlceID | Sehir |
| 101 | Yunus Yücel | 0532, 0212 | 1 | Mouse | 500 | 3401 | İstanbul |
| 102 | Ahmet Yılmaz | 0544 | 2 | Klavye | 1200 | 0602 | Ankara |
1. Adım: Birinci Normal Form (1NF)
Her hücre parçalanamaz (atomik) olmalıdır. Tablomuzdaki “Telefonlar” kolonunda birden fazla numara var. 1NF kuralına göre bu kabul edilemez. Tekilleştirme işlemi yapılmaktadır.
Yunus Yücel’in iki numarası olduğu için, her numara için ayrı bir satır oluşturuyoruz.
1NF Sonrası Tablo:
| SiparisID | MusteriAd | Telefon | UrunID | UrunAd | BirimFiyat | IlceID | Sehir |
| 101 | Yunus Yücel | 0532 | 1 | Mouse | 500 | 3401 | İstanbul |
| 101 | Yunus Yücel | 0212 | 1 | Mouse | 500 | 3401 | İstanbul |
| 102 | Ahmet Yılmaz | 0544 | 2 | Klavye | 1200 | 0602 | Ankara |
2. Adım: İkinci Normal Form (2NF)
1NF sağlanmalı ve anahtar olmayan kolonlar Birincil Anahtar’a (PK) tam bağımlı olmalıdır. Kısmi bağımlılıkları bitirmek, verileri ana tablolarına dağıtmak.
Yukarıdaki tabloda UrunAd ve BirimFiyat bilgileri siparişe değil ürüne aittir. Ayrıca Yunus Yücel’in telefonlarını kaybetmeden, isim tekrarından kurtulmak için telefonları ayrı bir tabloda ilişkilendiriyoruz.
Tablo: Siparisler (Siparişin Genel Bilgisi)
| SiparisID (PK) | MusteriAd | IlceID | Sehir |
| 101 | Yunus Yücel | 3401 | İstanbul |
| 102 | Ahmet Yılmaz | 0602 | Ankara |
Tablo: Musteri_Telefonlar (Tüm Numaralar Burada)
| TelefonID (PK) | SiparisID (FK) | Telefon |
| 1 | 101 | 0532 |
| 2 | 101 | 0212 |
| 3 | 102 | 0544 |
Tablo: Siparis_Detay (Hangi Siparişte Ne Var?)
| SiparisID (FK) | UrunID | UrunAd | BirimFiyat |
| 101 | 1 | Mouse | 500 |
| 102 | 2 | Klavye | 1200 |
3. Adım: Üçüncü Normal Form (3NF)
2NF sağlanmalı ve anahtar olmayan kolonlar arasında geçişli bağımlılık (transit dependency) olmamalıdır. Transit (geçişli) bağımlılıkları kaldırmak.
Anahtar olmayan “Sehir” kolonu, yine anahtar olmayan “IlceID” kolonuna bağlı. Bunu da ayırarak yapıyı tam profesyonel hale getiriyoruz.
Tablo: Ilceler (Bağımsız Coğrafi Bilgi)
| IlceID (PK) | Sehir |
| 3401 | İstanbul |
| 0602 | Ankara |
Tablo: Siparisler
| SiparisID (PK) | MusteriAd | IlceID (FK) |
| 101 | Yunus Yücel | 3401 |
| 102 | Ahmet Yılmaz | 0602 |
Bir MSSQL DBA veya geliştiricisi olarak sağlıklı bir yapı için şu adımları izlemelisiniz:
- İş Kurallarını Tanımlayın: Hangi verinin neyle ilişkili olduğunu netleştirin (Bire-Bir, Bire-Çok, Çoka-Çok).
- Primary Key Seçimi: Her tablonun mutlaka benzersiz bir kimlik kolonu (Identity, GUID vb.) olmalıdır.
- Foreign Keys Kullanın: Tablolar arasındaki ilişkiyi sadece mantıksal değil, fiziksel olarak da (Constraint) tanımlayın ki veri bütünlüğü bozulmasın.
- Dengeyi Kurun: Genellikle 3NF idealdir. Ancak çok büyük raporlama sistemlerinde performansı artırmak için bazen bilerek normalizasyondan kaçınılır (Denormalizasyon).
MSSQL Server’da normalizasyon, verinin “çöp” yığınına dönüşmesini engelleyen bir disiplindir. İyi normalize edilmiş bir veri tabanı, büyüme aşamasında (scalability) yöneticiye ve yazılımcıya en az sorunu çıkaran yapıdır. İlk başta daha fazla tablo oluşturmak zahmetli görünse de, uzun vadede sistemin hızı ve doğruluğu bu temelin sağlamlığına bağlıdır.
Unutmayın; yanlış tasarlanmış bir veri tabanını en güçlü SQL sorgusu bile kurtaramaz.
Başka makalede görüşmek dileğiyle..
Emanetlerinizi ve sözlerinizi tutun. Müminun-8
