İçeriğe geç
academia.sh

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 m×nm \times n yerine m+nm + n 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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat