Ders 09 / 14
İleri Normal Formlar
Boyce–Codd normal formunun tanımı ve üçüncü normal formdan farkı, bağımlılık korumanın yitirildiği ayrıştırma, çok değerli bağımlılık ile dördüncü normal form ve normalizasyonun durma noktası.
İçindekiler
Üçüncü normal form, anahtar dışı özniteliklere odaklanır: bunların ne anahtarın parçasına ne de başka bir anahtar dışı özniteliğe bağlı olmasını ister. Peki bir bağımlılığın sağ tarafı anahtarın parçasıysa? Tanım gereği o öznitelik anahtar dışı değildir, dolayısıyla üçüncü normal form ihlal edilmiş sayılmaz — buna karşılık aynı olgu birden çok satırda tekrar etmeye devam eder. Bu dersin sorusu şudur: bu boşluk nasıl kapatılır, ve kapatmanın bedeli nedir?
Boyce–Codd Normal Formu
Boyce–Codd normal formu (Boyce–Codd normal form) tek ve daha sıkı bir koşul koyar: önemsiz olmayan her işlevsel bağımlılığın sol tarafı bir süperanahtar olmalıdır. Üçüncü normal formdaki “anahtar dışı öznitelik” ayrıcalığı kalkar; hangi öznitelik olursa olsun, onu belirleyen kümenin anahtar olması gerekir.
İki tanımın ayrıştığı yer, aday anahtarların örtüştüğü bağıntılardır. Kütüphanede bir
kitabın hangi rafta durduğunu tutan bağıntıyı düşünelim. Kural şudur: bir kitap her şubede
tek bir rafta durur, ve her raf tek bir şubeye aittir. Buradan iki aday anahtar çıkar —
(isbn, sube_kodu) ve (isbn, raf) — ve bir de bağımlılık: raf → sube_kodu.
Bu bağıntı üçüncü normal formdadır: sube_kodu bir aday anahtarın parçası olduğu için
anahtar dışı sayılmaz. Ama raf bir süperanahtar değildir, dolayısıyla Boyce–Codd
koşulunu bozar. Sonucu şemanın uygulayamadığı bir tutarsızlıktır:
sqlite3 :memory: <<'SQL' .headers on .mode box CREATE TABLE yerlesim ( isbn TEXT NOT NULL, sube_kodu TEXT NOT NULL, raf TEXT NOT NULL, PRIMARY KEY (isbn, sube_kodu), UNIQUE (isbn, raf) ); INSERT INTO yerlesim VALUES ('975-01', 'MRK', 'R12'), ('975-02', 'MRK', 'R12'), ('975-03', 'BHC', 'R07'); INSERT INTO yerlesim VALUES ('975-04', 'BHC', 'R12'); SELECT raf, COUNT(DISTINCT sube_kodu) AS farkli_sube FROM yerlesim GROUP BY raf; SQL
┌─────┬─────────────┐ │ raf │ farkli_sube │ ├─────┼─────────────┤ │ R07 │ 1 │ │ R12 │ 2 │ └─────┴─────────────┘
Her iki aday anahtar da şemada yazılıdır ve hiçbiri ihlal edilmemiştir; buna rağmen R12
rafı iki ayrı şubede görünmektedir. raf → sube_kodu bağımlılığının sol tarafı anahtar
olmadığı için o kural şemaya yazılamaz, motorun onu bilmesinin bir yolu yoktur. Ayrıca
rafın şubesi, o raftaki her kitap için yeniden yazılmaktadır — tekrar sürer.
Ayrıştırma ve Bağımlılık Korumanın Yitirilmesi
Boyce–Codd ayrıştırması, bozan bağımlılığın sol tarafını yeni bir bağıntının anahtarı
yapar: raf(raf, sube_kodu) ve kitap_rafi(isbn, raf).
sqlite3 :memory: <<'SQL' .headers on .mode box PRAGMA foreign_keys = ON; CREATE TABLE raf (raf TEXT PRIMARY KEY NOT NULL, sube_kodu TEXT NOT NULL); CREATE TABLE kitap_rafi ( isbn TEXT NOT NULL, raf TEXT NOT NULL REFERENCES raf (raf), PRIMARY KEY (isbn, raf) ); INSERT INTO raf VALUES ('R12', 'MRK'), ('R07', 'BHC'), ('R21', 'MRK'); INSERT INTO kitap_rafi VALUES ('975-01', 'R12'), ('975-02', 'R12'), ('975-03', 'R07'); INSERT INTO kitap_rafi VALUES ('975-01', 'R21'); SELECT (SELECT COUNT(DISTINCT sube_kodu) FROM raf WHERE raf = 'R12') AS r12_sube, (SELECT COUNT(*) FROM kitap_rafi k JOIN raf r ON r.raf = k.raf WHERE k.isbn = '975-01' AND r.sube_kodu = 'MRK') AS kitap975_01_mrk; SQL
┌──────────┬─────────────────┐ │ r12_sube │ kitap975_01_mrk │ ├──────────┼─────────────────┤ │ 1 │ 2 │ └──────────┴─────────────────┘
İlk sütun kazancı gösterir: raf artık tek bir şubeye aittir ve bu kural anahtarla
uygulanmaktadır. İkinci sütun bedeli gösterir: 975-01 numaralı kitap Merkez şubesinde
iki ayrı rafta durmaktadır. Ayrıştırmadan önce bu satır yazılamazdı, çünkü
(isbn, sube_kodu) anahtardı.
Yitirilen şey (isbn, sube_kodu) → raf bağımlılığıdır. Bu bağımlılık artık iki bağıntının
hiçbirinde ifade edilemez; sınamak için ikisini birleştirmek gerekir. Buna bağımlılık
korumanın yitirilmesi denir ve Boyce–Codd normal formunun bilinen sınırıdır: her bağıntı
kayıpsız biçimde Boyce–Codd formuna ayrıştırılabilir, ancak bunu yaparken bağımlılık
korumak her zaman mümkün değildir.
Karar bu noktada tasarımcıya kalır. Hangi kuralın şemada uygulanması daha önemliyse ona göre seçilir: rafın tek şubeye ait olması mı, yoksa bir kitabın şube başına tek rafta durması mı? Üçüncü normal formda kalıp ikinci kuralı korumak da geçerli bir karardır — normal formlar bir merdiven değil, ödünleşim listesidir.
Çok Değerli Bağımlılık
Boyce–Codd normal formu işlevsel bağımlılıkları tüketir, ama tekrarın tek kaynağı bunlar değildir. Bir üyenin birden çok ilgi alanı ve birden çok telefon numarası varsa ve bu iki küme birbirinden bağımsızsa, üçünü tek bağıntıda tutmak kartezyen çarpım üretir. Buna çok değerli bağımlılık (multivalued dependency) denir.
Bağıntı Boyce–Codd formundadır — anahtar bütün özniteliklerden oluşur, dolayısıyla önemsiz olmayan hiçbir işlevsel bağımlılık yoktur. Yine de her yeni telefon numarası, üye kaç ilgi alanı taşıyorsa o kadar satır eklemeyi gerektirir:
sqlite3 :memory: <<'SQL' .headers on .mode box CREATE TABLE uye_birlesik (uye_no INTEGER, ilgi TEXT, telefon TEXT, PRIMARY KEY (uye_no, ilgi, telefon)); INSERT INTO uye_birlesik VALUES (41, 'tarih', '0312-555-0101'), (41, 'tarih', '0312-555-0102'), (41, 'tarih', '0312-555-0103'), (41, 'siir', '0312-555-0101'), (41, 'siir', '0312-555-0102'), (41, 'siir', '0312-555-0103'); CREATE TABLE uye_ilgi (uye_no INTEGER, ilgi TEXT, PRIMARY KEY (uye_no, ilgi)); CREATE TABLE uye_telefon (uye_no INTEGER, telefon TEXT, PRIMARY KEY (uye_no, telefon)); INSERT INTO uye_ilgi VALUES (41, 'tarih'), (41, 'siir'); INSERT INTO uye_telefon VALUES (41, '0312-555-0101'), (41, '0312-555-0102'), (41, '0312-555-0103'); INSERT INTO uye_ilgi VALUES (41, 'gezi'); INSERT INTO uye_birlesik VALUES (41, 'gezi', '0312-555-0101'); SELECT (SELECT COUNT(*) FROM uye_birlesik) AS birlesik_satir, (SELECT COUNT(*) FROM uye_ilgi) + (SELECT COUNT(*) FROM uye_telefon) AS ayrik_satir, (SELECT COUNT(*) FROM uye_ilgi i JOIN uye_telefon t USING (uye_no)) AS birlestirilmis; SQL
┌────────────────┬─────────────┬────────────────┐ │ birlesik_satir │ ayrik_satir │ birlestirilmis │ ├────────────────┼─────────────┼────────────────┤ │ 7 │ 6 │ 9 │ └────────────────┴─────────────┴────────────────┘
Üçüncü ilgi alanı eklenirken tek satır yazıldı ve birleşik bağıntı yedi satırda kaldı;
tutarlı olması için dokuz satır olmalıydı. Sessiz bir tutarsızlık doğdu: gezi ilgi
alanına sahip üyenin yalnız bir telefonu varmış gibi görünüyor. Ayrık bağıntılarda toplam
altı satır tutuldu ve birleştirme doğru dokuz satırı üretti. Fark, satır sayısının
yerine ile büyümesidir.
Dördüncü normal form (fourth normal form), önemsiz olmayan her çok değerli bağımlılığın sol tarafının süperanahtar olmasını ister. Uygulamadaki karşılığı yalın bir kuraldır: birbirinden bağımsız iki çok değerli olgu aynı bağıntıda tutulmaz.
Daha İleri Formlar
Beşinci normal form (fifth normal form), bağıntının ikiye değil ancak üç ya da daha çok parçaya bölündüğünde kayıpsız ayrıştırılabildiği durumları ele alır; bu durumu doğuran kısıta birleştirme bağımlılığı (join dependency) denir. Gerçek şemalarda seyrek görülür ve genellikle üçlü bir ilişkinin gerçekte üç ikili ilişkiden oluştuğu durumlarda ortaya çıkar.
Kilit ve anahtar normal formu (domain-key normal form) ise ölçütü en genel biçimde koyar: bağıntı üzerindeki her kısıt, yalnız alan tanımlarından ve anahtarlardan türetilebilmelidir. Bu koşulu sağlayan bir bağıntıda hiçbir güncelleme anomalisi bulunamaz. Kuramsal bir hedef olarak değerlidir; her bağıntı için ulaşılabilir değildir ve ulaşıldığının sınanması genel olarak yapılamaz.
Nerede Durmalı
Uygulamada tasarımların çoğu üçüncü normal formda ya da Boyce–Codd formunda durur. Karar ölçütü, formun numarası değil şu iki sorudur: hangi anomaliler gerçekten ortaya çıkabilir, ve bunları önleyen kısıt şemada yazılabiliyor mu?
İzlenecek sıra da bellidir. Önce alanın kuralları — yani işlevsel ve çok değerli bağımlılıklar — yazılır. Sonra aday anahtarlar kapanış hesabıyla bulunur. Sonra sol tarafı anahtar olmayan bağımlılıklar aranır; her biri ya bir ayrıştırmaya ya da bilinçli bir istisnaya dönüşür. İstisna kararı yazılı kalmalıdır, çünkü bir sonraki tasarımcı için o yapı hata gibi görünecektir.
Özet
- Boyce–Codd normal formu, önemsiz olmayan her bağımlılığın sol tarafının süperanahtar olmasını ister; üçüncü normal formdaki anahtar dışı ayrıcalığını kaldırır.
- İki form yalnız aday anahtarların örtüştüğü bağıntılarda ayrışır; üçüncü normal formda kalan bir şema, uygulanamayan bir bağımlılık barındırabilir.
- Her bağıntı kayıpsız biçimde Boyce–Codd formuna ayrıştırılabilir, ancak bağımlılık koruma her zaman sağlanamaz; hangi kuralın şemada uygulanacağı bir tasarım kararıdır.
- Bağımsız iki çok değerli olgu aynı bağıntıda tutulduğunda satır sayısı çarpımla büyür ve eksik satır sessiz tutarsızlık üretir; dördüncü normal form bunu ayırır.
- Normal formlar bir merdiven değil ödünleşim listesidir; durma noktası, gerçekten ortaya çıkabilecek anomalilere göre seçilir.
Sonraki Adım
Buraya kadarki bütün adımlar aynı yönde ilerledi: tekrarı kaldır, bağıntıyı böl, kuralı şemaya yazdır. Bunun ödenmemiş bir bedeli vardır — bölünen her bağıntı, okuma sırasında yeniden birleştirilmek zorundadır. Sıradaki ders bu bedeli ölçer ve ters yöndeki kararı ele alır: tekrarı bilerek geri koymak hangi koşulda savunulabilir, ve karşılığında hangi yazma maliyeti üstlenilir?
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.