1/60Normalizacja baz danych – 5NF: Piąta postać normalna

Zależności złączeniowe – ostatni krok normalizacji relacyjnej

Zakładamy znajomość 1NF, 2NF, 3NF, BCNF i 4NF.

Ta prezentacja kończy cykl normalizacji na przykładzie systemu bibliotecznego. Wprowadza zależności złączeniowe (JD) – ostatnią i najrzadszą formę normalizacji w modelu relacyjnym.

5NF została zdefiniowana przez Ronalda Fagina w 1979 roku. To najwyższa forma normalizacji w modelu relacyjnym – kropka nad 'i'.
Slajd tytułowy – przejście od 4NF do 5NF, ostatni krok normalizacji relacyjnej

Piąta postać normalna, znana również jako PJ/NF (Project-Join Normal Form), została wprowadzona przez Ronalda Fagina w 1979 roku jako naturalne uogólnienie czwartej postaci normalnej. Stanowi ona teoretyczne domknięcie procesu normalizacji relacyjnych baz danych, eliminując ostatnią klasę anomalii związanych z zależnościami złączeniowymi. W przeciwieństwie do wcześniejszych postaci normalnych, 5NF nie koncentruje się na zależnościach funkcyjnych ani wielowartościowych, lecz bada bardziej subtelne powiązania między atrybutami.

Podstawowym pojęciem leżącym u podstaw piątej postaci normalnej jest zależność złączeniowa, oznaczana symbolem gwiazdki i zbioru podzbiorów atrybutów. JD stwierdza, że relację można bezstratnie rozłożyć na szereg projekcji, które po złączeniu dają dokładnie oryginalną relację bez dodawania fałszywych wierszy. Jest to zatem bezpośrednie uogólnienie koncepcji zależności wielowartościowej, która operuje wyłącznie na dwóch podzbiorach atrybutów.

W praktyce inżynierii oprogramowania piąta postać normalna rzadko znajduje bezpośrednie zastosowanie, co wynika z faktu, że relacje spełniające warunki JD bez jednoczesnego wynika z kluczy kandydujących są niezwykle rzadkie. Mimo to znajomość 5NF stanowi istotny element wykształcenia każdego projektanta baz danych, pozwalając na pełne zrozumienie teoretycznych podstaw modelu relacyjnego i jego ograniczeń.

2/60Agenda prezentacji – plan podróży przez 60 slajdów

Sześć części – od powtórki do podsumowania cyklu

Prezentacja składa się z sześciu części:

  • Część 0: Powtórka – od 1NF do 4NF (slajdy 1-8)
  • Część I: Co to są zależności złączeniowe (JD)? (slajdy 9-18)
  • Część II: Definicja 5NF (slajdy 19-28)
  • Część III: Przykład z biblioteką – relacje trójskładnikowe (slajdy 29-40)
  • Część IV: Implementacja i weryfikacja w MariaDB (slajdy 41-52)
  • Część V: Podsumowanie całego cyklu normalizacji (slajdy 53-60)
5NF to finał normalizacji. Po 4NF wciąż mogą być problemy – JD. 5NF je eliminuje. Potem: już nic. Koniec.
Mapa prezentacji – sześć części połączonych strzałkami

Niniejsza prezentacja została podzielona na pięć zasadniczych części, prowadzących słuchacza od podstaw teoretycznych przez konkretne przykłady aż po implementację w systemie MariaDB. Rozpoczniemy od przypomnienia kluczowych koncepcji czwartej postaci normalnej oraz zależności wielowartościowych, które stanowią niezbędny fundament do zrozumienia bardziej zaawansowanego materiału. Następnie przejdziemy do szczegółowego omówienia zależności złączeniowych, które są centralnym pojęciem piątej postaci normalnej.

Druga część prezentacji skupi się na formalnej definicji 5NF oraz na analizie warunków, jakie musi spełniać relacja, aby znajdować się w tej postaci normalnej. Szczególną uwagę poświęcimy relacji między JD a kluczami kandydującymi, która decyduje o tym, czy dana tabela wymaga dalszej dekompozycji. W części trzeciej przedstawimy praktyczny przykład systemu rekomendacji bibliotecznych obrazujący działanie mechanizmu JD w konkretnym kontekście biznesowym.

Część czwarta zawierać będzie szczegółową demonstrację implementacji w MariaDB krok po kroku, od tworzenia tabel, przez testowanie JD, aż po weryfikację poprawności dekompozycji. Ostatnia część stanowi podsumowanie całego cyklu normalizacji od 1NF do 5NF, zestawiając ze sobą wszystkie postaci normalne i omawiając ich praktyczne zastosowania w rzeczywistych systemach bazodanowych.

3/60Powtórka: gdzie jesteśmy po 4NF?

Przebyta droga od 1NF do 4NF

  • 1NF: atomowość, brak grup, klucz główny
  • 2NF: eliminacja zależności częściowych
  • 3NF: eliminacja zależności przechodnich
  • BCNF: zamknięcie furtek 3NF – każdy wyznacznik to nadklucz
  • 4NF: eliminacja zależności wielowartościowych (MVD) – niezależne listy

Po 4NF: każda MVD wynika z klucza. Ale wciąż jest jeden krok – 5NF.

Przeszliśmy długą drogę: od jednej tabeli z bałaganem do 8 czystych tabel. Ale wciąż jest jeden krok – 5NF.
Droga normalizacji – od 1NF do 4NF z zaznaczeniem 5NF jako ostatniego kroku

Po przejściu przez kolejne etapy normalizacji od 1NF do 4NF nasz schemat bazy danych biblioteki osiągnął już wysoki poziom czystości strukturalnej. Pierwsza postać normalna zapewniła atomowość wartości i eliminację powtarzających się grup, druga usunęła częściowe zależności funkcyjne, trzecia wyeliminowała zależności przechodnie, a BCNF uporał się z problemem nakładających się kluczy kandydujących. Czwarta postać normalna wniosła kluczową poprawkę dotyczącą niezależnych list atrybutów, rozdzielając zależności wielowartościowe na osobne tabele.

Obecny schemat składa się z ośmiu tabel, z których każda przechowuje informacje dotyczące jednej konkretnej encji lub związku między encjami. Mimo że struktura ta wydaje się kompletna i pozbawiona oczywistych wad, teoria normalizacji wskazuje na istnienie jeszcze jednego rodzaju zależności, który może powodować ukryte problemy. Zależności te dotyczą sytuacji, w których trzy lub więcej zbiorów atrybutów pozostają ze sobą w specyficznej relacji wykraczającej poza prostą parę niezależnych list.

Właśnie ten brakujący element analizy stanowi przedmiot zainteresowania piątej postaci normalnej. Zrozumienie, dlaczego 4NF nie jest ostatnim krokiem normalizacji, wymaga spojrzenia na problem z szerszej perspektywy uwzględniającej nie tylko pary zbiorów atrybutów, ale także bardziej złożone struktury wieloskładnikowe. To właśnie ta perspektywa prowadzi do odkrycia zależności złączeniowych i definicji 5NF.

4/60Powtórka: co to są zależności wielowartościowe (MVD)?

MVD – Multi-Valued Dependency

MVD: A →→ B (A wielowyznacza B) – dla danej wartości A, zbiór wartości B.

Przykład: ID_Czyt →→ Telefon (czytelnik ma wiele telefonów).

  • MVD to szczególny przypadek JD (dla dwóch podzbiorów)
  • 4NF eliminuje MVD poprzez rozdzielenie na osobne tabele
  • Ale: co jeśli są WIĘCEJ niż dwa niezależne zbiory? Wtedy JD → 5NF
MVD = JD dla dwóch zbiorów. 4NF = 5NF dla dwóch zbiorów. Ale JD może dotyczyć trzech lub więcej zbiorów – wtedy potrzebna jest 5NF.
MVD jako szczególny przypadek JD – dwa zbiory vs trzy zbiory

Zależność wielowartościowa, oznaczana symbolem A →→ B, stanowi rozszerzenie koncepcji zależności funkcyjnej na przypadki, w których danej wartości atrybutu A odpowiada zbiór wartości atrybutu B. W przeciwieństwie do zależności funkcyjnej, która mówi o dokładnie jednej wartości wyznaczanej przez poprzednik, MVD dopuszcza istnienie wielu niezależnych wartości dla tego samego wyznacznika. Typowym przykładem jest sytuacja, w której jeden czytelnik posiada wiele numerów telefonów lub adresów e-mail, a każda z tych list jest od siebie niezależna.

Kluczowa własność zależności wielowartościowej polega na tym, że generuje ona swoisty produkt kartezjański pomiędzy niezależnymi zbiorami wartości. Jeśli czytelnik ma trzy telefony i dwa adresy e-mail, to w tabeli zgodnej wyłącznie z BCNF pojawi się sześć wierszy, co stanowi źródło nadmiarowości. Rozwiązaniem oferowanym przez czwartą postać normalną jest wydzielenie każdej niezależnej listy do osobnej tabeli, co eliminuje niepożądany efekt mnożenia wierszy.

Zależność wielowartościowa jest szczególnym przypadkiem zależności złączeniowej dla sytuacji, w której występują dokładnie dwa podzbiory atrybutów. Formalnie rzecz biorąc, MVD A →→ B | C jest równoważna JD *{A ∪ B, A ∪ C}, co w praktyce oznacza, że każdą tabelę z MVD można bezstratnie rozłożyć na dwie projekcje. To ścisłe powiązanie między MVD a JD stanowi klucz do zrozumienia, dlaczego 5NF jest naturalnym uogólnieniem 4NF.

5/60Powtórka: nasz schemat biblioteki po 4NF

Obecny schemat (8 tabel)

  • Czytelnicy (ID_Czyt, Imie, Nazwisko, ID_Miasta)
  • Miasta (ID_Miasta, Nazwa, KodPocztowy)
  • Ksiazki (ISBN, Tytul, RokWydania)
  • Wypozyczenia (ID_Wyp, ID_Czyt, ISBN, DataWyp, DataZwrotu)
  • Opiekunowie (ID_Czyt, ID_Bibliotekarza)
  • Przypisania_BCNF (ID_Czyt, ISBN, DataPrzypisania)
  • Telefony (ID_Czyt, Telefon, TypTel)
  • Emaile (ID_Czyt, Email, TypEmail)

Wszystkie tabele w 4NF – żadnych MVD, żadnych nielegalnych FD.

8 tabel, każda w 4NF. Wydaje się, że to koniec. Ale teoria normalizacji ma jeszcze jeden as – zależności złączeniowe.
Schemat bazy biblioteki po 4NF – 8 tabel połączonych kluczami obcymi

Po pełnym procesie normalizacji do czwartej postaci normalnej schemat bazy bibliotecznej składa się z ośmiu wyspecjalizowanych tabel spełniających rygorystyczne kryteria integralności danych. Tabela Czytelnicy przechowuje dane osobowe czytelników z kluczem głównym ID_Czytelnika, natomiast tabela Miasta stanowi słownik zawierający przypisanie kodów pocztowych do miejscowości. Książki są reprezentowane przez tabelę z atrybutami ISBN, Tytul i RokWydania, która pełni rolę centralnego katalogu zbiorów bibliotecznych.

Tabela Wypozyczenia łączy ze sobą czytelników i książki, przechowując informacje czasowe dotyczące każdego zdarzenia wypożyczenia, natomiast tabela Opiekunowie realizuje relację wiele-do-wielu między czytelnikami a bibliotekarzami. Przypisania_BCNF zawiera dodatkowe atrybuty związane z przypisaniem książek do czytelników, które wymagały osobnej tabeli ze względu na specyfikę zależności funkcyjnych. Tabele Telefony i Emaile przechowują dane kontaktowe czytelników, rozdzielone zgodnie z wymaganiami 4NF.

Wszystkie osiem tabel znajduje się w czwartej postaci normalnej, co oznacza, że żadna z nich nie zawiera zależności wielowartościowych niewynikających z kluczy kandydujących. Mimo tego zaawansowanego poziomu normalizacji, wciąż istnieje teoretyczna możliwość wystąpienia zależności złączeniowych, które nie są wykrywane przez mechanizmy 4NF. To właśnie te ukryte zależności, dotyczące trzech lub więcej zbiorów atrybutów, stanowią przedmiot analizy w piątej postaci normalnej.

6/60Powtórka: czego 4NF nie eliminuje?

4NF eliminuje MVD – ale istnieją zależności między WIĘCEJ niż dwoma zbiorami

  • 4NF eliminuje MVD – zależności między dwoma zbiorami wartości
  • Ale: istnieją zależności między WIĘCEJ niż dwoma zbiorami
  • Przykład: relacja trójskładnikowa (A, B, C) gdzie wszystkie pary są niezależne
  • Jeśli (A, B), (A, C) i (B, C) są niezależne – 4NF nie wychwytuje problemu

5NF eliminuje te zależności – to ostatnia postać normalna.

4NF mówi: 'rozdziel na dwie tabele'. 5NF mówi: 'rozdziel na trzy (lub więcej) tabele'. 5NF to uogólnienie 4NF.
4NF vs 5NF – 4NF eliminuje MVD (dwa zbiory), 5NF eliminuje JD (wiele zbiorów)

Czwarta postać normalna skutecznie eliminuje problemy związane z niezależnymi listami atrybutów, jednak jej zakres ogranicza się wyłącznie do przypadków binarnych, czyli sytuacji z dokładnie dwoma zbiorami wartości. Mechanizm zależności wielowartościowych nie jest w stanie opisać bardziej złożonych związków między trzema lub większą liczbą niezależnych wymiarów danych. Wyobraźmy sobie tabelę zawierającą informacje o książkach, autorach i bibliotekarzach, gdzie każda para tych encji może występować w dowolnej kombinacji, ale niekoniecznie wszystkie trójki są dozwolone.

W takiej sytuacji 4NF nie sygnalizuje żadnego problemu, ponieważ pomiędzy żadną parą atrybutów nie występuje niezależność wielowartościowa w klasycznym rozumieniu. Każdy atrybut z osobna może być powiązany z pozostałymi w sposób, który nie generuje redundantnych produktów kartezjańskich. Jednak z punktu widzenia teorii normalizacji taka tabela może wciąż zawierać ukrytą zależność złączeniową, która umożliwia bezstratny podział na trzy mniejsze relacje.

Różnica między 4NF a 5NF sprowadza się więc do liczby analizowanych podzbiorów atrybutów: 4NF bada pary, podczas gdy 5NF rozważa dowolną liczbę zbiorów. To uogólnienie sprawia, że piąta postać normalna stanowi najbardziej restrykcyjne kryterium normalizacji w modelu relacyjnym. W praktyce oznacza to, że tabela może spełniać wszystkie warunki 4NF, a jednocześnie nie znajdować się w 5NF, jeśli istnieje w niej JD niewynikająca z kluczy kandydujących.

7/60Powtórka: co to jest zależność złączeniowa (JD)?

JD – Join Dependency

  • JD: *{A, B, C} – relację R można bezstratnie podzielić na projekcje A, B, C
  • Znaczenie: JOIN projekcji daje oryginalną relację (bez dodatkowych wierszy)
  • JD to uogólnienie MVD – MVD to JD dla dwóch zbiorów
  • Jeśli JD istnieje: tabelę można rozłożyć na mniejsze tabele
  • Jeśli JD nie wynika z kluczy: tabela nie jest w 5NF
JD mówi: 'możesz podzielić tę tabelę na kolumny, złączyć z powrotem i dostać to samo'. Jeśli NIE możesz – potrzebujesz 5NF, żeby to sprawdzić.
Wizualizacja JD – podział tabeli na projekcje i złączenie z powrotem

Zależność złączeniowa to stwierdzenie, że relację R można bezstratnie podzielić na co najmniej dwie projekcje, których naturalne złączenie daje w wyniku dokładnie tę samą relację R. Formalnie zapisuje się ją jako *{X₁, X₂, ..., Xₙ}, gdzie każde Xᵢ stanowi podzbiór atrybutów relacji R, a suma wszystkich Xᵢ pokrywa wszystkie atrybuty R. Jeśli dana JD jest spełniona przez relację, oznacza to, że w każdej dopuszczalnej instancji tej relacji zachodzi równość między relacją a złączeniem jej projekcji.

Intuicyjnie rzecz ujmując, JD orzeka, że informacja zawarta w relacji R jest w pewnym sensie złożona z niezależnych fragmentów, które mogą być przechowywane osobno bez utraty danych. Własność ta ma fundamentalne znaczenie dla projektowania baz danych, ponieważ wskazuje na możliwość dekompozycji tabel bez ryzyka utraty informacji. Jeśli JD nie jest spełniona, próba rozkładu i ponownego złączenia projekcji wygeneruje dodatkowe, fałszywe wiersze, które nie występowały w oryginalnej relacji.

Zależność złączeniowa stanowi bezpośrednie uogólnienie zależności wielowartościowej: podczas gdy MVD dotyczy dwóch podzbiorów atrybutów, JD może obejmować dowolną liczbę podzbiorów. W szczególności każda MVD A →→ B | C jest równoważna JD *{A ∪ B, A ∪ C}, co pokazuje, że teoria normalizacji rozwija się od przypadków szczególnych ku coraz bardziej ogólnym sformułowaniom. To właśnie ta hierarchiczna struktura zależności stanowi podstawę do definiowania kolejnych postaci normalnych.

8/60Wprowadzenie do problemu: po co 5NF?

Tabela w 4NF może wciąż mieć problemy – JD niewynikające z kluczy

  • Przykład: KsiazkiAutorzyBibliotekarze (ISBN, Autor, ID_Bibliotekarza)
  • 4NF: brak MVD (nie ma dwóch niezależnych list – są trzy wymiary)
  • Ale: czy tabelę można bezstratnie rozłożyć na trzy tabele binarne?
  • Jeśli tak: JD istnieje. Jeśli nie: tabela jest w porządku (5NF spełniona)

5NF bada, czy JD wynika z kluczy kandydujących.

5NF to odpowiedź na pytanie: 'czy tę tabelę da się podzielić na mniejsze bez utraty informacji?' Jeśli tak – trzeba podzielić.
Problem 5NF – tabela w 4NF, ale z potencjalną JD

Po przejściu przez wszystkie wcześniejsze etapy normalizacji, w tym wymagającą czwartą postać normalną, projektant bazy danych może odnieść wrażenie, że schemat jest już całkowicie optymalny. Jednak teoria normalizacji dowodzi, że istnieje jeszcze jedna klasa problemów związanych z zależnościami złączeniowymi, które nie są wykrywane przez żadną z wcześniejszych postaci normalnych. Problem pojawia się wtedy, gdy relacja zawiera trzy lub więcej atrybutów, a reguły biznesowe dopuszczają dowolne kombinacje między poszczególnymi parami tych atrybutów.

Rozważmy tabelę zawierającą trzy kolumny: ISBN książki, nazwisko autora oraz identyfikator bibliotekarza. W tej tabeli każdy bibliotekarz może polecać dowolną książkę, każdy bibliotekarz może polecać dowolnego autora, a każda książka ma swoich autorów. Mimo że wszystkie te stwierdzenia są prawdziwe, nie oznacza to automatycznie, że każdy bibliotekarz poleca każdego autora w każdej książce – ta ostatnia kombinacja może być niedozwolona przez reguły biznesowe.

Pytanie, na które odpowiada 5NF, brzmi: czy z faktu, że istnieją pewne pary (ISBN, autor), (ISBN, bibliotekarz) i (autor, bibliotekarz), wynika konieczność istnienia całej trójki (ISBN, autor, bibliotekarz)? Jeśli odpowiedź brzmi tak, to JD jest spełniona i tabelę należy podzielić na trzy mniejsze. Jeśli nie, tabela pozostaje w 5NF, ponieważ JD nie wynika z danych ani z kluczy kandydujących, a zatem dekompozycja nie jest wymagana.

9/60Definicja zależności złączeniowej (JD)

JD – definicja formalna

  • Oznaczenie: *{A₁, A₂, ..., Aₙ} gdzie Aᵢ są podzbiorami atrybutów R
  • Znaczenie: R = ⋈(R[A₁], R[A₂], ..., R[Aₙ]) – bezstratne złączenie projekcji
  • Inaczej: dla każdego możliwego stanu bazy, złączenie projekcji daje ORYGINALNE dane
  • Jeśli JD jest spełniona: tabelę można rozłożyć bez utraty informacji
  • Jeśli JD nie jest spełniona: rozkład da dodatkowe (fałszywe) wiersze
JD = 'rozkład bezstratny'. Jeśli złączysz projekcje i dostaniesz więcej wierszy niż na początku – JD nie jest spełniona.
Definicja JD – schemat złączenia projekcji dających oryginalną relację

Niech R będzie relacją o zbiorze atrybutów U, a A₁, A₂, ..., Aₙ będą podzbiorami U takimi, że suma wszystkich Aᵢ równa się U. Mówimy, że w relacji R zachodzi zależność złączeniowa *{A₁, A₂, ..., Aₙ}, jeśli dla każdej dopuszczalnej instancji relacji R zachodzi równość R = π_{A₁}(R) ⋈ π_{A₂}(R) ⋈ ... ⋈ π_{Aₙ}(R). Innymi słowy, relacja R jest dokładnie równa naturalnemu złączeniu swoich projekcji na podzbiory A₁, A₂, ..., Aₙ, co oznacza, że rozkład na te projekcje jest bezstratny.

Symbol gwiazdki poprzedzający listę podzbiorów atrybutów jest standardowym oznaczeniem przyjętym w literaturze bazodanowej dla zależności złączeniowych. Każdy podzbiór Aᵢ może zawierać jeden lub więcej atrybutów, a liczba podzbiorów n jest zawsze większa lub równa dwa. W przypadku n równego dwa zależność złączeniowa redukuje się do zależności wielowartościowej, co potwierdza, że MVD jest szczególnym przypadkiem JD.

Weryfikacja, czy dana JD jest spełniona przez konkretną instancję relacji, polega na wykonaniu operacji złączenia projekcji i porównaniu wyniku z oryginalną relacją. Jeśli wynik złączenia zawiera więcej wierszy niż oryginał, oznacza to, że JD nie jest spełniona. Jeśli natomiast liczba wierszy jest identyczna, JD zachodzi i relację można bezpiecznie zdekomponować. Ta własność stanowi podstawę praktycznego testowania JD w systemach zarządzania bazami danych.

10/60JD – intuicyjne wyjaśnienie

Intuicja stojąca za JD

  • Wyobraź sobie tabelę z kolumnami A, B, C
  • Jeśli między nimi nie ma żadnych zależności – każda kombinacja (A, B, C) jest możliwa
  • Ale w rzeczywistości: nie wszystkie kombinacje występują
  • JD bada: czy jeśli istnieją (A₁, B₁), (A₁, C₁), (B₁, C₁) – to czy musi istnieć (A₁, B₁, C₁)?
  • Jeśli TAK – JD jest spełniona (można rozłożyć)
  • Jeśli NIE – JD nie jest spełniona (tabeli nie da się rozłożyć)
JD zadaje pytanie: 'czy z tego, że para AB istnieje, para AC istnieje i para BC istnieje, wynika, że cała trójka ABC istnieje?' Odpowiedź decyduje o 5NF.
Intuicyjne wyjaśnienie JD – trzy pary decydują o trójce

Aby zrozumieć istotę zależności złączeniowej w sposób intuicyjny, warto posłużyć się prostym przykładem z trzema zbiorami danych. Wyobraźmy sobie trzy listy: listę par (ISBN, autor) oznaczającą, które książki napisali którzy autorzy, listę par (ISBN, bibliotekarz) określającą, które książki polecają poszczególni bibliotekarze, oraz listę par (autor, bibliotekarz) informującą, których autorów polecają bibliotekarze. Każda z tych list stanowi projekcję pewnej nadrzędnej relacji trójskładnikowej na konkretną parę atrybutów.

Zależność złączeniowa bada, czy z istnienia wszystkich trzech list par wynika automatycznie istnienie wszystkich możliwych kombinacji trójek. Inaczej mówiąc, jeśli wiemy, że książka o danym ISBN ma określonego autora, że ten sam ISBN jest polecany przez pewnego bibliotekarza oraz że ten sam autor jest polecany przez tego samego bibliotekarza, to czy musimy wnioskować, że ów bibliotekarz poleca właśnie tę książkę tego autora? Jeśli odpowiedź jest twierdząca, oznacza to, że między atrybutami zachodzi zależność złączeniowa.

W praktyce odpowiedź na to pytanie zależy wyłącznie od reguł biznesowych obowiązujących w modelowanej rzeczywistości. Jeśli system dopuszcza wszystkie kombinacje, JD jest spełniona i relację można rozłożyć. Jeśli natomiast istnieją konkretne ograniczenia biznesowe wykluczające niektóre kombinacje, JD nie zachodzi, a relacja pozostaje nierozłożona. To właśnie te reguły biznesowe, a nie struktura matematyczna, decydują ostatecznie o tym, czy 5NF wymaga dalszej dekompozycji.

11/60JD ≠ MVD – porównanie

Porównanie MVD i JD

CechaMVDJD
OznaczenieA →→ B*{A, B, C}
Liczba zbiorów2n (≥ 2)
Relacja z 4NF/5NF4NF5NF
PrzykładID_Czyt →→ Telefon*{ISBN, Autor, ID_Bib}
W praktyceRzadkaBardzo rzadka
MVD jako JDMVD = *{A, B, R-A-B}JD uogólnia MVD
MVD to JD dla dwóch zbiorów. JD to MVD dla wielu zbiorów. 5NF to uogólnienie 4NF.
Tabela porównawcza MVD vs JD

Zależności wielowartościowe i zależności złączeniowe stanowią dwie strony tej samej monety, różniące się przede wszystkim liczbą analizowanych podzbiorów atrybutów. MVD, oznaczana jako A →→ B, opisuje sytuację, w której zbiór atrybutów A determinuje zbiór wartości atrybutów B niezależnie od pozostałych atrybutów C = R - A - B. JD natomiast, zapisywana jako *{A₁, A₂, ..., Aₙ}, uogólnia to pojęcie na dowolną liczbę podzbiorów, nie ograniczając się do przypadku trzech komplementarnych zbiorów.

Z punktu widzenia hierarchii normalizacji, 4NF eliminuje wszystkie MVD niewynikające z kluczy kandydujących, podczas gdy 5NF rozszerza to wymaganie na wszystkie JD. Oznacza to, że każda relacja w 5NF jest automatycznie w 4NF, ale relacja w 4NF może nie znajdować się w 5NF, jeśli istnieje w niej JD, która nie jest MVD. Ta hierarchiczna zależność między postaciami normalnymi odzwierciedla rosnący poziom restrykcyjności wymagań nakładanych na strukturę danych.

W praktyce różnica między MVD a JD ma istotne znaczenie dla zrozumienia, jakiego rodzaju anomalie mogą pozostać nierozwiązane po osiągnięciu 4NF. O ile MVD prowadzi do redundantnych produktów kartezjańskich między dwiema niezależnymi listami, o tyle JD może powodować bardziej subtelne problemy związane z wymuszoną obecnością lub brakiem określonych kombinacji atrybutów. Rozpoznanie, z którym typem zależności mamy do czynienia, wymaga dogłębnej analizy reguł biznesowych i struktury kluczy kandydujących.

12/60Kiedy powstaje JD?

Warunki powstania JD

  • Gdy trzy (lub więcej) encje są w relacji trójskładnikowej
  • Gdy każda para encji może wystąpić niezależnie od trzeciej
  • Gdy reguły biznesowe nie wymuszają zależności między parami
  • Typowy przykład: 'Książka, Autor, Bibliotekarz'
  • - Książka ma wielu autorów
  • - Książkę poleca wielu bibliotekarzy
  • - Autor jest polecany przez wielu bibliotekarzy
  • - Ale: nie każdy autor książki jest polecany przez każdego bibliotekarza polecającego tę książkę
JD powstaje, gdy masz trójskładnikową relację, ale każda para żyje własnym życiem. To rzadkie, ale możliwe.
Warunki powstania JD – trzy encje w relacji trójskładnikowej

Zależności złączeniowe powstają w specyficznych okolicznościach, które w praktyce występują niezwykle rzadko, ale są dobrze zdefiniowane teoretycznie. Podstawowym warunkiem koniecznym jest obecność relacji trójskładnikowej lub wyższego rzędu, czyli takiej, w której występują co najmniej trzy atrybuty lub grupy atrybutów powiązane ze sobą w sposób niezależny. Nie wystarczy jednak sama obecność trzech atrybutów – konieczne jest, aby każda para tych atrybutów mogła występować niezależnie od wartości trzeciego atrybutu.

Klasycznym przykładem prowadzącym do JD jest relacja między książką, autorem i bibliotekarzem, gdzie każdy bibliotekarz może polecać dowolną książkę niezależnie od autora, a także polecać dowolnego autora niezależnie od konkretnej książki. W takiej sytuacji każda para encji tworzy własną, niezależną relację binarną, a wszystkie trzy relacje binarne istnieją równolegle. Problem pojawia się, gdy reguły biznesowe nie wymuszają żadnych dodatkowych ograniczeń na kombinacje trójek poza tymi, które wynikają z par.

Aby JD zaistniała w praktyce, muszą być spełnione trzy warunki: relacja musi zawierać co najmniej trzy atrybuty, każda para atrybutów musi być od siebie niezależna w tym sensie, że wartości w jednej parze nie determinują wartości w trzecim atrybucie, oraz wszystkie kombinacje par muszą być dozwolone przez reguły biznesowe. Spełnienie tych trzech warunków jednocześnie jest w realnych systemach na tyle rzadkie, że wielu programistów nigdy nie spotyka JD w swojej karierze zawodowej.

13/60Przykład z biblioteką: relacja trójskładnikowa

Tabela Rekomendacje – trzy encje

Tabela KsiazkiAutorzyBibliotekarze: (ISBN, Autor, ID_Bibliotekarza)

Znaczenie: bibliotekarz X poleca książkę Y autorstwa Z.

Założenie: wszystkie trzy informacje są niezależne.

  • (ISBN1, AutorA, Bib1) – Bib1 poleca książkę ISBN1 autorstwa A
  • (ISBN1, AutorB, Bib2) – Bib2 poleca książkę ISBN1 autorstwa B
  • (ISBN2, AutorA, Bib2) – Bib2 poleca książkę ISBN2 autorstwa A
  • To czy musi istnieć (ISBN1, AutorA, Bib2)? NIE – jeśli nie ma JD, to nie musi
Mamy trzy fakty: Bib1 lubi książkę ISBN1, Bib2 lubi autora A, ISBN1 ma autora A. Czy Bib2 lubi książkę ISBN1? NIE KONIECZNIE – to właśnie bada JD.
Relacja trójskładnikowa – ISBN, Autor, ID_Bibliotekarza

W przykładowej bazie bibliotecznej wprowadzamy nową funkcjonalność systemu rekomendacji, która pozwala bibliotekarzom polecać czytelnikom konkretne książki określonych autorów. Do przechowywania tych informacji tworzymy tabelę Rekomendacje o schemacie zawierającym trzy kolumny: ISBN identyfikujący książkę, Autor określający twórcę dzieła oraz ID_Bibliotekarza wskazującego na pracownika biblioteki. Klucz główny tej tabeli jest złożony ze wszystkich trzech kolumn, co oznacza, że każda kombinacja (ISBN, autor, bibliotekarz) może wystąpić co najwyżej raz.

Reguły biznesowe w tym systemie są następujące: każdy bibliotekarz może polecać dowolną książkę bez względu na to, kto jest jej autorem, oraz może polecać dowolnego autora bez względu na to, które książki tego autora znajdują się w zbiorach. Oznacza to, że relacje binarne między parami encji są w pełni niezależne: relacja między ISBN a autorem wynika z faktu autorstwa, relacja między ISBN a bibliotekarzem odzwierciedla polecenie książki, a relacja między autorem a bibliotekarzem reprezentuje polecenie twórcy. Te trzy niezależne wymiary stanowią idealne podłoże do wystąpienia zależności złączeniowej.

W analizie tej struktury kluczowe pytanie brzmi: czy z faktu, że dany bibliotekarz poleca konkretną książkę oraz że poleca również konkretnego autora, i że ta książka została napisana przez tego autora, wynika automatycznie, że bibliotekarz poleca tę książkę tego autora? Jeśli reguły biznesowe nie nakładają dodatkowych ograniczeń, odpowiedź brzmi twierdząco i JD jest spełniona. W przeciwnym razie, gdy pewne kombinacje są wykluczone przez politykę biblioteki, JD nie zachodzi i tabela pozostaje w 5NF.

14/60Problem: gdy JD nie jest spełniona

Przykład danych – JD nie spełniona

Tabela KsiazkiAutorzyBibliotekarze z danymi:

  • (978-83-123-4567-1, 'Stefan Żeromski', 1) – Bib1 poleca Żeromskiego, książka 1
  • (978-83-123-4567-1, 'Bolesław Prus', 2) – Bib2 poleca Prusa, książka 1
  • (978-83-123-4567-2, 'Stefan Żeromski', 2) – Bib2 poleca Żeromskiego, książka 2

Czy JD *{ISBN, Autor}, {ISBN, Bib}, {Autor, Bib} jest spełniona?

  • Para (ISBN1, Żeromski): TAK (pierwszy wiersz)
  • Para (ISBN1, Bib2): TAK (drugi wiersz)
  • Para (Żeromski, Bib2): TAK (trzeci wiersz)
  • Jeśli JD spełniona: (ISBN1, Żeromski, Bib2) MUSI istnieć

Ale w danych: NIE MA tego wiersza! JD NIE jest spełniona.

Wszystkie pary istnieją, ale trójka (ISBN1, Żeromski, Bib2) nie istnieje. JD nie jest spełniona – tabeli NIE DA SIĘ bezstratnie rozłożyć.
Problem JD – wszystkie pary istnieją, ale trójka nie

Rozpatrzmy konkretny przykład danych w tabeli Rekomendacje, który ilustruje sytuację, gdy zależność złączeniowa nie jest spełniona. Załóżmy, że mamy trzy wiersze: bibliotekarz o identyfikatorze 1 poleca książkę o numerze ISBN1 autorstwa Żeromskiego, bibliotekarz 2 poleca tę samą książkę ISBN1 autorstwa Prusa, a bibliotekarz 2 poleca również inną książkę ISBN2 autorstwa Żeromskiego. W tej sytuacji wszystkie trzy możliwe pary atrybutów są reprezentowane para ISBN1 i Żeromski występuje w pierwszym wierszu, para ISBN1 i bibliotekarz 2 występuje w drugim wierszu, a para Żeromski i bibliotekarz 2 występuje w trzecim wierszu.

Gdyby zależność złączeniowa *{ISBN, Autor}, {ISBN, ID_Bibliotekarza}, {Autor, ID_Bibliotekarza} była spełniona, to w tabeli musiałby istnieć wiersz (ISBN1, Żeromski, bibliotekarz 2), ponieważ wszystkie trzy składające się na niego pary są obecne. Analiza danych pokazuje jednak, że taki wiersz nie istnieje, co oznacza, że JD nie jest spełniona. Konsekwencją tego faktu jest to, że próba rozłożenia tabeli na trzy projekcje binarne i ponownego ich złączenia wygeneruje dodatkowy, nieistniejący w oryginalnych danych wiersz.

Z praktycznego punktu widzenia brak spełnienia JD oznacza, że w systemie obowiązuje konkretna reguła biznesowa: bibliotekarz 2 nie poleca Żeromskiego w książce ISBN1, mimo że poleca samego Żeromskiego oraz poleca książkę ISBN1 w innym kontekście. Taka reguła może wynikać z subiektywnych preferencji bibliotekarza, który ceni twórczość Żeromskiego, ale nie uważa książki ISBN1 za godną polecenia. W tym przypadku tabeli nie należy rozkładać, ponieważ JD nie jest spełniona, a zatem 5NF jest zachowana.

15/60Kiedy JD jest spełniona?

Warunki spełnienia JD

JD *{A, B, C} jest spełniona, gdy:

  • Dla każdej pary (a₁, b₁) w R[A, B]
  • I każdej pary (a₁, c₁) w R[A, C]
  • I każdej pary (b₁, c₁) w R[B, C]
  • TO (a₁, b₁, c₁) istnieje w R

W przykładzie: jeśli dodamy (ISBN1, Żeromski, Bib2) – JD zostanie spełniona.

Wtedy: R = R[A,B] ⋈ R[A,C] ⋈ R[B,C] (złączenie bezstratne).

JD spełniona = wszystkie kombinacje istnieją. Wtedy możesz rozłożyć na trzy tabele binarne. Jeśli brakuje choć jednej kombinacji – nie możesz.
JD spełniona – wszystkie kombinacje trójek istnieją

Zależność złączeniowa jest spełniona wtedy i tylko wtedy, gdy dla każdej kombinacji par atrybutów występujących w odpowiednich projekcjach istnieje odpowiadający jej wiersz w relacji wyjściowej. Innymi słowy, jeśli w projekcji na podzbiór A znajduje się para (a₁, b₁), w projekcji na podzbiór B znajduje się para (a₁, c₁), a w projekcji na podzbiór C znajduje się para (b₁, c₁), to w relacji R musi istnieć wiersz (a₁, b₁, c₁). Spełnienie tego warunku dla wszystkich możliwych kombinacji jest konieczne i wystarczające do tego, aby JD zachodziła.

W kontekście naszego przykładu bibliotecznego, JD byłaby spełniona, gdybyśmy dodali do tabeli Rekomendacje czwarty wiersz (ISBN1, Żeromski, bibliotekarz 2). Wówczas wszystkie kombinacje par wynikające z trzech projekcji byłyby reprezentowane w pełnej relacji trójskładnikowej. Złączenie projekcji binarnych na (ISBN, Autor), (ISBN, ID_Bibliotekarza) i (Autor, ID_Bibliotekarza) dałoby w wyniku dokładnie cztery wiersze identyczne z oryginalną tabelą, co potwierdza bezstratność dekompozycji.

W praktyce spełnienie JD oznacza, że reguły biznesowe nie nakładają żadnych ograniczeń na kombinacje atrybutów poza tymi, które wynikają z samych par. Jeśli bibliotekarz może polecać dowolną książkę, dowolnego autora, a każda książka ma swoich autorów, to automatycznie każda kombinacja tych trzech elementów jest dozwolona. W takiej sytuacji przechowywanie wszystkich kombinacji w jednej tabeli jest nieefektywne i lepiej rozłożyć ją na trzy mniejsze, co właśnie nakazuje 5NF.

16/60Wizualizacja: złączenie projekcji

Jak działa złączenie projekcji?

Tabela R: (ISBN, Autor, ID_Bib)

Projekcje:

  • R1: (ISBN, Autor) – jacy autorzy napisali jakie książki
  • R2: (ISBN, ID_Bib) – którzy bibliotekarze polecają jakie książki
  • R3: (Autor, ID_Bib) – których autorów polecają bibliotekarze

Złączenie R1 ⋈ R2 ⋈ R3:

  • Łączy R1 i R2 po ISBN → tymczasowa tabela (ISBN, Autor, ID_Bib)
  • Potem łączy z R3 po (Autor, ID_Bib)
  • Wynik: WSZYSTKIE możliwe kombinacje pasujących par
Złączenie projekcji = sprawdzenie JD. Jeśli wynik daje WIĘCEJ wierszy niż oryginał – JD nie jest spełniona. Jeśli tyle samo – jest spełniona.
Wizualizacja – trzy projekcje złączone w jedną tabelę

Operacja złączenia projekcji stanowi podstawowe narzędzie weryfikacji zależności złączeniowych i może być łatwo zwizualizowana na konkretnym przykładzie. Załóżmy, że nasza relacja Rekomendacje zawiera cztery wiersze spełniające JD i chcemy sprawdzić, czy rozkład na trzy tabele binarne jest rzeczywiście bezstratny. W tym celu wykonujemy trzy projekcje: pierwsza zawiera pary (ISBN, Autor), druga zawiera pary (ISBN, ID_Bibliotekarza), a trzecia zawiera pary (Autor, ID_Bibliotekarza). Każda z tych projekcji jest mniejsza od oryginalnej relacji, ponieważ zawiera wyłącznie dwie kolumny.

Następnym krokiem jest wykonanie naturalnego złączenia tych trzech projekcji, które odbywa się w dwóch etapach. Najpierw łączymy pierwszą i drugą projekcję po wspólnym atrybucie ISBN, otrzymując tymczasową relację zawierającą trzy kolumny: ISBN, Autor i ID_Bibliotekarza. Następnie łączymy tę tymczasową relację z trzecią projekcją po wspólnych atrybutach Autor i ID_Bibliotekarza. Wynik końcowy powinien zawierać dokładnie te same wiersze, co oryginalna relacja, jeśli JD jest spełniona.

Gdyby zależność złączeniowa nie była spełniona, złączenie projekcji wygenerowałoby dodatkowe wiersze nieobecne w oryginalnej relacji. Dzieje się tak dlatego, że operacja złączenia naturalnego tworzy wszystkie kombinacje pasujących par, nawet jeśli odpowiadająca im trójka nie istnieje w rzeczywistości. Wizualizacja tego mechanizmu pomaga zrozumieć, dlaczego test złączenia jest tak skutecznym narzędziem do wykrywania JD: jeśli wynik złączenia pokrywa się z oryginałem, dekompozycja jest bezpieczna, w przeciwnym razie prowadzi do utraty integralności danych.

17/60JD w praktyce – jak często występuje?

JD jest niezwykle rzadka w praktyce

  • Większość systemów nigdy nie spotyka JD w rzeczywistych danych
  • 5NF jest głównie akademicka – pokazuje 'kraniec' teorii normalizacji
  • Aby JD wystąpiła, muszą być spełnione specyficzne warunki:
  • 1. Relacja trójskładnikowa (lub więcej)
  • 2. Wszystkie pary niezależne
  • 3. Wszystkie kombinacje istnieją (lub nie istnieją) w specyficzny sposób
  • W praktyce: jeśli tabela jest w 3NF i ma prosty klucz – jest w 5NF
JD to biały krab normalizacji – rzadkość, ale gdy się pojawi, wymaga 5NF. Większość programistów nigdy nie spotka JD w praktyce.
Rzadkość JD – metafora białego kraba

Zależności złączeniowe należą do najrzadziej występujących zjawisk w praktyce projektowania i eksploatacji systemów bazodanowych. Większość profesjonalnych programistów i administratorów baz danych pracuje przez całą swoją karierę, nie napotykając ani razu na sytuację, w której JD wymagałaby ingerencji w strukturę tabel. Szacuje się, że w standardowych systemach informatycznych, takich jak systemy ERP, CRM czy platformy e-commerce, odsetek tabel, które mogłyby potencjalnie naruszać 5NF, wynosi poniżej 0,01% wszystkich relacji.

Taka rzadkość wynika z faktu, że JD wymaga jednoczesnego spełnienia kilku restrykcyjnych warunków, które rzadko występują razem w rzeczywistych aplikacjach. Po pierwsze, tabela musi modelować relację trójskładnikową lub wyższego rzędu, co samo w sobie nie jest częste w dobrze zaprojektowanych schematach. Po drugie, każda para atrybutów musi być od siebie w pełni niezależna, co w praktyce oznacza brak jakichkolwiek ograniczeń biznesowych nakładanych na konkretne kombinacje wartości. Po trzecie, wszystkie możliwe kombinacje par muszą być dozwolone przez reguły biznesowe.

W rezultacie większość relacji trójskładnikowych w rzeczywistych systemach zawiera dodatkowe atrybuty opisujące konkretne powiązanie między encjami, takie jak data, ilość, cena czy ocena, które uniemożliwiają spełnienie JD. Na przykład w tabeli zawierającej informacje o lekarzach, pacjentach i lekach z atrybutem Dawka, wartość dawki zależy od całej trójki, co wyklucza możliwość dowolnych kombinacji. Dlatego też 5NF pozostaje głównie w sferze rozważań akademickich, choć jej znajomość jest istotna dla pełnego zrozumienia teorii normalizacji.

18/605NF a praktyka – czy warto?

5NF – głównie akademicka

  • 5NF jest głównie akademicka – w praktyce niezwykle rzadka
  • Wymaga skomplikowanej analizy zależności między atrybutami
  • Większość systemów zatrzymuje się na 3NF lub BCNF
  • Jeśli tabela ma prosty klucz główny (jedna kolumna) – prawie na pewno jest w 5NF
  • Koszt 5NF: więcej tabel, bardziej złożone zapytania
  • Zysk: teoretyczna czystość, brak ukrytych zależności
5NF to 'ekskluzywny klub' normalizacji – większość tabel nie spełnia warunków do rozkładu JD, więc 5NF jest automatycznie spełniona. Ciesz się, że nie musisz jej używać.
5NF – praktyczne znaczenie i wartość akademicka

Praktyczna wartość piątej postaci normalnej jest przedmiotem dyskusji w środowisku inżynierów baz danych, ponieważ jej zastosowanie wiąże się z korzyściami teoretycznymi, ale także z konkretnymi kosztami implementacyjnymi. Z jednej strony 5NF zapewnia najwyższy możliwy poziom czystości strukturalnej, eliminując wszystkie znane typy anomalii związanych z dekompozycją relacji. Z drugiej strony osiągnięcie 5NF wymaga wprowadzenia dodatkowych tabel, co zwiększa złożoność zapytań i może negatywnie wpływać na wydajność operacji odczytu.

W praktyce inżynierskiej przyjmuje się, że zatrzymanie się na trzeciej postaci normalnej lub BCNF jest w zupełności wystarczające dla zdecydowanej większości systemów produkcyjnych. Czwarta postać normalna jest stosowana w sytuacjach, gdy występują niezależne listy atrybutów, takich jak numery telefonów czy adresy e-mail, ale i to nie jest regułą. Piąta postać normalna znajduje zastosowanie niemal wyłącznie w systemach o bardzo restrykcyjnych wymaganiach integralności danych lub w specyficznych domenach, gdzie modelowanie wielowymiarowe jest szczególnie istotne.

Należy pamiętać, że większość tabel w rzeczywistych systemach jest automatycznie w 5NF, ponieważ zawiera prosty klucz główny składający się z jednej kolumny. W takich przypadkach wszystkie JD wynikają w sposób naturalny z kluczy kandydujących, a zatem analiza 5NF nie wnosi żadnych nowych informacji. Decyzja o stosowaniu 5NF powinna być zatem podejmowana świadomie, z uwzględnieniem konkretnych wymagań projektowych i analizy kosztów i korzyści, a nie jako automatyczny krok w procesie normalizacji.

19/60Definicja formalna 5NF (PJ/NF – Project-Join Normal Form)

5NF – definicja

Relacja R jest w 5NF, jeśli:

  • Jest w 4NF (warunek konieczny)
  • Każda zależność złączeniowa *{A₁, A₂, ..., Aₙ} w R wynika z kluczy kandydujących R

Inaczej: każdy bezstratny rozkład R na projekcje musi być oparty na kluczach kandydujących.

  • Jeśli wszystkie JD są konsekwencją kluczy – 5NF spełniona
  • Jeśli istnieje JD niewynikająca z kluczy – tabela nie jest w 5NF
5NF wymaga, aby każdy możliwy podział tabeli był 'naturalny' – czyli wynikał z kluczy, a nie z przypadkowych zależności między danymi.
Definicja 5NF – warunki konieczne i wystarczające

Relacja R znajduje się w piątej postaci normalnej, zwanej również Project-Join Normal Form, wtedy i tylko wtedy, gdy spełnia dwa warunki. Po pierwsze, relacja R musi być w czwartej postaci normalnej, co oznacza, że nie zawiera żadnych zależności wielowartościowych niewynikających z kluczy kandydujących. Po drugie, każda zależność złączeniowa *{A₁, A₂, ..., Aₙ} zachodząca w relacji R musi wynikać z kluczy kandydujących tej relacji, co w praktyce oznacza, że każdy podzbiór Aᵢ musi być nadkluczem relacji R.

Innymi słowy, 5NF wymaga, aby każdy możliwy bezstratny rozkład relacji na projekcje był uzasadniony strukturą kluczy kandydujących, a nie przypadkowymi zależnościami między danymi. Jeśli istnieje JD, która nie wynika z kluczy kandydujących, oznacza to, że tabelę można podzielić na mniejsze części w sposób, który nie jest oczywisty z punktu widzenia integralności referencyjnej. W takiej sytuacji 5NF nakazuje dokonanie dekompozycji w celu wyeliminowania ukrytej zależności.

Nazwa Project-Join Normal Form pochodzi od sposobu, w jaki definiuje się tę postać normalną poprzez badanie związku między operacjami projekcji i złączenia. W odróżnieniu od wcześniejszych postaci normalnych, które koncentrowały się na zależnościach funkcyjnych i wielowartościowych, 5NF bada ogólną własność dekompozycyjności relacji. To sprawia, że 5NF jest najbardziej fundamentalną postacią normalną w modelu relacyjnym, ponieważ dotyka samej istoty tego, co oznacza bezstratny podział informacji.

20/605NF – warunki szczegółowo

Dwa warunki 5NF w praktyce

  • Warunek 1: tabela musi być w 4NF (brak MVD od nie-klucza)
  • Warunek 2: dla każdej JD *{A₁, ..., Aₙ}, każdy Aᵢ musi być nadkluczem (lub wynikać z kluczy)
  • W praktyce: jeśli tabela ma tylko jeden klucz kandydujący (prosty lub złożony), to:
  • - Wszystkie JD wynikają z tego klucza
  • - Tabela jest automatycznie w 5NF
  • Problem pojawia się tylko przy złożonych kluczach kandydujących i relacjach wieloskładnikowych
5NF jest prawie zawsze automatycznie spełniona – chyba że masz naprawdę skomplikowaną strukturę kluczy i zależności.
Warunki 5NF – schemat blokowy decyzji

Warunek pierwszy piątej postaci normalnej wymaga, aby relacja znajdowała się w 4NF, co jest konieczne, ale nie wystarczające do osiągnięcia 5NF. Czwarta postać normalna gwarantuje, że wszystkie zależności wielowartościowe wynikają z kluczy kandydujących, co eliminuje problem niezależnych list atrybutów. Jednak 4NF nie bada bardziej złożonych zależności między trzema lub większą liczbą zbiorów atrybutów, które mogą prowadzić do ukrytych anomalii niewidocznych na poziomie par atrybutów.

Warunek drugi stanowi sedno definicji 5NF: każda zależność złączeniowa w relacji musi wynikać z kluczy kandydujących. Oznacza to, że jeśli istnieje JD *{A₁, A₂, ..., Aₙ}, to dla każdego podzbioru Aᵢ zachodzi jedna z dwóch możliwości: albo Aᵢ zawiera klucz kandydujący relacji R, albo JD jest logiczną konsekwencją innych JD, które już wynikają z kluczy. W praktyce najczęściej oznacza to, że każdy podzbiór Aᵢ musi być nadkluczem, czyli minimalnym identyfikatorem wiersza.

Weryfikacja warunku drugiego w praktyce sprowadza się do sprawdzenia, czy istnieje jakakolwiek JD, której żaden z podzbiorów nie zawiera klucza kandydującego. Jeśli taka JD istnieje i jest spełniona przez dane, relacja nie znajduje się w 5NF i wymaga dekompozycji. Jeśli natomiast wszystkie JD w relacji wynikają z kluczy, 5NF jest spełniona i dalsza normalizacja nie jest potrzebna. W przypadku relacji z pojedynczym kluczem kandydującym warunek ten jest prawie zawsze spełniony automatycznie.

21/60JD a klucze kandydujące

Związek między JD a kluczami

  • Jeśli JD *{A₁, A₂, ..., Aₙ} wynika z kluczy kandydujących:
  • - Oznacza, że każdy Aᵢ zawiera klucz kandydujący
  • - Lub: JD jest konsekwencją istnienia kluczy
  • W przykładzie: klucz = (ISBN, Autor, ID_Bib) – JEDEN klucz kandydujący
  • - JD *{ISBN, Autor}, {ISBN, ID_Bib}, {Autor, ID_Bib} NIE wynika z tego klucza
  • - Żaden z podzbiorów nie zawiera klucza
  • - Jeśli JD jest spełniona – tabelę trzeba rozłożyć
Klucz (ISBN, Autor, Bib) – żaden z podzbiorów JD nie zawiera klucza. Jeśli JD jest spełniona, trzeba rozłożyć. Jeśli nie – tabela jest w porządku.
JD a klucze kandydujące – które podzbiory zawierają klucz?

Związek między zależnościami złączeniowymi a kluczami kandydującymi ma fundamentalne znaczenie dla zrozumienia piątej postaci normalnej. Klucz kandydujący to minimalny zbiór atrybutów, który jednoznacznie identyfikuje każdy wiersz w relacji, a w 5NF wymagamy, aby każda JD była w pewnym sensie pochodną tych kluczy. Konkretnie, JD *{A₁, A₂, ..., Aₙ} wynika z kluczy kandydujących wtedy, gdy każdy podzbiór Aᵢ zawiera co najmniej jeden klucz kandydujący relacji R.

Rozważmy naszą przykładową tabelę Rekomendacje z kluczem kandydującym (ISBN, Autor, ID_Bibliotekarza). JD, którą analizujemy, to *{ISBN, Autor}, {ISBN, ID_Bibliotekarza}, {Autor, ID_Bibliotekarza}. Żaden z podzbiorów tej JD nie zawiera pełnego klucza kandydującego, ponieważ każdy z nich składa się z dwóch atrybutów, podczas gdy klucz ma ich trzy. Oznacza to, że ta JD nie wynika z kluczy kandydujących, a zatem jeśli jest spełniona przez dane, relacja nie znajduje się w 5NF.

W praktyce oznacza to, że im więcej kluczy kandydujących ma relacja, tym większa szansa, że JD będą z nich wynikać. Relacje z jednym prostym kluczem głównym są niemal zawsze w 5NF, ponieważ każda JD, która nie zawiera tego klucza, nie może być spełniona w sposób nierozkładalny. Z kolei relacje z wieloma złożonymi kluczami kandydującymi wymagają dokładniejszej analizy, ponieważ mogą zawierać JD, które nie wynikają wprost z żadnego z istniejących kluczy.

22/60Różnica między MVD a JD – szczegółowo

MVD vs JD – porównanie formalne

  • MVD (4NF): dotyczy dwóch zbiorów atrybutów
  • - A →→ B | C oznacza: R = R[A, B] ⋈ R[A, C]
  • - Dekompozycja: zawsze na DWIE tabele
  • JD (5NF): dotyczy wielu zbiorów atrybutów
  • - *{A, B, C} oznacza: R = R[A] ⋈ R[B] ⋈ R[C]
  • - Dekompozycja: na n tabel (n ≥ 2)
  • MVD to szczególny przypadek JD:
  • - A →→ B | C ⇔ *{A ∪ B, A ∪ C}
  • 4NF = 5NF dla przypadku binarnego (dwuelementowego)
4NF to 5NF dla dwóch zbiorów. 5NF to 4NF dla wielu zbiorów. Każda tabela w 5NF jest w 4NF, ale nie odwrotnie.
MVD vs JD – diagram Venna

Szczegółowe porównanie zależności wielowartościowych i złączeniowych ujawnia hierarchiczną strukturę teorii normalizacji, w której każda kolejna postać normalna rozszerza zakres analizowanych zależności. MVD dotyczy ściśle dwóch zbiorów atrybutów, które uzupełniają się do pełnego zbioru atrybutów relacji, co zapisujemy jako A →→ B | C, gdzie C = R - A - B. Z kolei JD może obejmować dowolną liczbę podzbiorów, których suma pokrywa wszystkie atrybuty, ale nie muszą one być parami rozłączne ani komplementarne.

Różnica w liczbie analizowanych podzbiorów przekłada się bezpośrednio na zakres stosowalności 4NF i 5NF. Czwarta postać normalna bada wyłącznie przypadki binarne, co oznacza, że wykrywa problemy związane z dwiema niezależnymi listami atrybutów. Jeśli jednak mamy trzy lub więcej niezależnych wymiarów danych, 4NF pozostaje ślepa na istniejącą zależność, ponieważ nie istnieje MVD, która by ją opisywała. W takiej sytuacji konieczne jest zastosowanie bardziej ogólnego narzędzia, jakim jest JD.

Warto zauważyć, że każda MVD jest szczególnym przypadkiem JD, ale nie każda JD jest MVD. Konkretnie, MVD A →→ B | C jest równoważna JD *{A ∪ B, A ∪ C}. Oznacza to, że 4NF jest szczególnym przypadkiem 5NF dla relacji, w których wszystkie JD są dwuelementowe. W tym sensie 5NF stanowi naturalne uogólnienie 4NF, a przejście od 4NF do 5NF polega na rozszerzeniu analizy z przypadków dwuelementowych na przypadki wieloelementowe.

23/60Kiedy tabela nie jest w 5NF?

Warunki naruszenia 5NF

  • Gdy istnieje JD *{A, B, C}, która nie wynika z kluczy kandydujących
  • Gdy rozkład na tabele (A,B), (A,C), (B,C) daje przy złączeniu dodatkowe, nieistniejące wiersze
  • Gdy rozkład na tabele (A,B), (A,C), (B,C) traci istniejące wiersze
  • W praktyce: bardzo rzadka sytuacja, wymagająca specyficznych reguł biznesowych
  • Warunek konieczny: tabela musi mieć co najmniej 3 atrybuty (inaczej JD jest trywialna)
Tabela nie w 5NF = rzadkość. Jeśli znajdziesz taką – to jak wygrana w loterii (ale w negatywnym sensie).
Kiedy 5NF jest naruszona? – schemat decyzyjny

Tabela nie znajduje się w piątej postaci normalnej wtedy i tylko wtedy, gdy istnieje w niej zależność złączeniowa, która nie wynika z kluczy kandydujących, a jednocześnie jest spełniona przez bieżący stan danych. Innymi słowy, muszą być spełnione trzy warunki jednocześnie: musi istnieć JD o odpowiedniej strukturze, JD musi wynikać z reguł biznesowych lub danych, oraz JD nie może być konsekwencją istniejących kluczy kandydujących. Dopiero spełnienie wszystkich trzech warunków oznacza naruszenie 5NF i konieczność dekompozycji.

W praktyce naruszenie 5NF jest sytuacją wyjątkowo rzadką, ponieważ wymaga specyficznej konfiguracji struktury tabeli i reguł biznesowych. Tabela musi mieć co najmniej trzy atrybuty, ponieważ JD dla dwóch atrybutów jest zawsze trywialna. Ponadto wszystkie pary atrybutów muszą być od siebie niezależne, co oznacza, że nie istnieją żadne zależności funkcyjne ani wielowartościowe, które ograniczałyby kombinacje. Wreszcie, dane muszą potwierdzać, że wszystkie możliwe kombinacje par faktycznie występują w relacji.

W przypadku naszej tabeli Rekomendacje, naruszenie 5NF wystąpiłoby dopiero wtedy, gdyby reguły biznesowe zezwalały na dowolne kombinacje wszystkich trzech atrybutów, a dane odzwierciedlałyby tę swobodę. Jeśli natomiast istnieje choćby jedna reguła ograniczająca kombinacje, JD nie jest spełniona, a tabela automatycznie znajduje się w 5NF. To wyjaśnia, dlaczego w praktyce tak trudno znaleźć tabelę naruszającą 5NF: większość systemów ma bogate reguły biznesowe, które naturalnie ograniczają dozwolone kombinacje.

24/60Rozkład do 5NF – zasada ogólna

Dekompozycja do 5NF

Dla JD *{A₁, A₂, ..., Aₙ}, gdzie JD nie wynika z kluczy:

  • Utwórz tabelę dla każdego Aᵢ (projekcja atrybutów)
  • Każda tabela ma klucz złożony z atrybutów Aᵢ
  • Usuń oryginalną tabelę

W przykładzie JD *{ISBN, Autor}, {ISBN, Bib}, {Autor, Bib}:

  • KsiazkiAutorzy (ISBN, Autor)
  • KsiazkiBibliotekarze (ISBN, ID_Bib)
  • AutorzyBibliotekarze (Autor, ID_Bib)

Każda tabela ma klucz (para atrybutów).

Dekompozycja 5NF: jedna tabela na każdy podzbiór JD. Trzy podzbiory = trzy tabele. Każda przechowuje relację między parą encji.
Rozkład do 5NF – jedna tabela na trzy podzbiory

Dekompozycja relacji do piątej postaci normalnej przebiega według prostej i powtarzalnej procedury opartej na zbiorach atrybutów występujących w zależności złączeniowej. Dla każdego podzbioru Aᵢ występującego w JD *{A₁, A₂, ..., Aₙ} tworzymy osobną tabelę zawierającą wyłącznie atrybuty należące do tego podzbioru. Każda nowa tabela otrzymuje klucz główny złożony z atrybutów wchodzących w skład danego podzbioru, co zapewnia jednoznaczną identyfikację wierszy w ramach tej projekcji.

W naszym przykładzie JD *{ISBN, Autor}, {ISBN, ID_Bibliotekarza}, {Autor, ID_Bibliotekarza} prowadzi do utworzenia trzech tabel binarnych. Pierwsza tabela o nazwie KsiazkiAutorzy zawiera kolumny ISBN i Autor z kluczem złożonym z obu atrybutów. Druga tabela KsiazkiBibliotekarze przechowuje pary ISBN i ID_Bibliotekarza, również z kluczem złożonym. Trzecia tabela AutorzyBibliotekarze zawiera atrybuty Autor i ID_Bibliotekarza, a jej kluczem jest para tych dwóch kolumn.

Po dokonaniu dekompozycji każda z nowych tabel automatycznie znajduje się w 5NF, ponieważ ma prostą strukturę z jednym kluczem kandydującym i żadnymi złożonymi zależnościami między atrybutami. Wszystkie JD w tych tabelach są trywialne i wynikają wprost z kluczy głównych. Należy pamiętać, że dekompozycję wykonujemy wyłącznie wtedy, gdy JD jest faktycznie spełniona przez dane w przeciwnym razie prowadzi ona do utraty integralności danych i generowania fałszywych wierszy przy złączeniu.

25/60Weryfikacja 5NF po dekompozycji

Sprawdzenie, czy nowe tabele są w 5NF

  • KsiazkiAutorzy: (ISBN, Autor) – klucz: (ISBN, Autor) – JD wynikają z klucza ✔
  • KsiazkiBibliotekarze: (ISBN, ID_Bib) – klucz: (ISBN, ID_Bib) – JD wynikają z klucza ✔
  • AutorzyBibliotekarze: (Autor, ID_Bib) – klucz: (Autor, ID_Bib) – JD wynikają z klucza ✔

Każda tabela ma prostą strukturę – jeden klucz, żadnych złożonych zależności.

Wszystkie tabele w 5NF (automatycznie, bo mają tylko jeden klucz kandydujący).

Po dekompozycji każda tabela ma jeden klucz – i jest automatycznie w 5NF. Dekompozycja upraszcza strukturę.
Weryfikacja 5NF – trzy tabele binarne z kluczami

Po dokonaniu dekompozycji relacji na mniejsze tabele zgodnie z zasadami 5NF, konieczne jest przeprowadzenie weryfikacji, czy każda z nowych tabel rzeczywiście spełnia wymagania piątej postaci normalnej. W przypadku tabel binarnych, takich jak KsiazkiAutorzy z kluczem (ISBN, Autor), weryfikacja jest stosunkowo prosta, ponieważ każda tabela ma tylko jeden klucz kandydujący złożony z obu atrybutów. Wszystkie potencjalne JD w takiej tabeli są trywialne, ponieważ każdy podzbiór atrybutów zawiera niepusty fragment klucza.

Kluczowym aspektem weryfikacji jest upewnienie się, że podczas dekompozycji nie utraciliśmy żadnych informacji ani nie wprowadziliśmy fałszywych danych. Test bezstratności złączenia polega na wykonaniu naturalnego złączenia wszystkich trzech tabel binarnych i porównaniu wyniku z oryginalną relacją. Jeśli liczba wierszy w wyniku złączenia jest identyczna z liczbą wierszy w oryginalnej tabeli, dekompozycja jest bezstratna i poprawna. Jeśli natomiast wynik złączenia zawiera więcej wierszy, oznacza to, że JD nie była spełniona, a dekompozycja została wykonana błędnie.

Dodatkowym elementem weryfikacji jest sprawdzenie integralności referencyjnej między nowymi tabelami a pozostałymi tabelami w schemacie bazy danych. Każda nowa tabela powinna mieć zdefiniowane klucze obce łączące ją z odpowiednimi tabelami nadrzędnymi, na przykład kolumna ISBN w tabeli KsiazkiAutorzy powinna być kluczem obcym prowadzącym do tabeli Ksiazki. Zapewnienie tych powiązań gwarantuje, że dane w zdekomponowanych tabelach pozostają spójne z resztą systemu.

26/60Ćwiczenie 1: zidentyfikuj JD

Tabela DostawyProduktyDostawcy

Tabela DostawyProduktyDostawcy: (ID_Dostawy, ID_Produktu, ID_Dostawcy, Data, Cena)

Założenie: każdy produkt może być dostarczany przez każdego dostawcę, każda dostawa zawiera wiele produktów.

JD: *{ID_Dostawy, ID_Produktu}, {ID_Dostawy, ID_Dostawcy, Data}, {ID_Produktu, ID_Dostawcy}

Pytanie: czy ta JD wynika z kluczy?

  • Klucz: (ID_Dostawy, ID_Produktu) – JEDEN klucz
  • Podzbiory JD (ID_Dostawy, ID_Dostawcy, Data) nie zawierają klucza
  • Jeśli JD jest spełniona – tabela nie jest w 5NF
Ćwiczenie: trzy podzbiory JD. Jeden z nich (ID_Dostawy, ID_Dostawcy, Data) nie zawiera klucza. Jeśli JD spełniona → nie w 5NF.
Ćwiczenie 1 – tabela DostawyProduktyDostawcy

W pierwszym ćwiczeniu praktycznym analizujemy tabelę DostawyProduktyDostawcy zawierającą atrybuty ID_Dostawy, ID_Produktu, ID_Dostawcy, Data oraz Cena. Klucz główny tej tabeli stanowi para atrybutów (ID_Dostawy, ID_Produktu), która jednoznacznie identyfikuje każdy wiersz. Potencjalna zależność złączeniowa, którą należy zbadać, to *{ID_Dostawy, ID_Produktu}, {ID_Dostawy, ID_Dostawcy, Data}, {ID_Produktu, ID_Dostawcy}. Celem ćwiczenia jest ustalenie, czy ta JD wynika z kluczy kandydujących, a jeśli nie, czy jest spełniona przez dane.

Analiza rozpoczyna się od sprawdzenia, czy którykolwiek z podzbiorów JD zawiera klucz kandydujący. Podzbiór pierwszy {ID_Dostawy, ID_Produktu} jest dokładnie równy kluczowi głównemu, co oznacza, że ten element JD wynika z kluczy. Jednak pozostałe dwa podzbiory, {ID_Dostawy, ID_Dostawcy, Data} oraz {ID_Produktu, ID_Dostawcy}, nie zawierają pełnego klucza kandydującego, ponieważ żaden z nich nie obejmuje jednocześnie ID_Dostawy i ID_Produktu. Zatem JD jako całość nie wynika bezpośrednio z kluczy kandydujących.

W drugim kroku należy sprawdzić, czy JD jest spełniona przez konkretne dane w tabeli. Wymaga to wykonania testu złączenia projekcji i porównania liczby wierszy. Jeśli wszystkie możliwe kombinacje par z trzech projekcji istnieją w oryginalnej tabeli, JD jest spełniona i tabela nie znajduje się w 5NF. W przeciwnym razie, gdy pewne kombinacje są wykluczone przez reguły biznesowe, JD nie zachodzi, a tabela pozostaje w 5NF. Wynik ćwiczenia zależy zatem od konkretnych danych biznesowych.

27/60Ćwiczenie 2: zaprojektuj dekompozycję do 5NF

Dekompozycja tabeli DostawyProduktyDostawcy

JD: *{ID_Dostawy, ID_Produktu}, {ID_Dostawy, ID_Dostawcy, Data}, {ID_Produktu, ID_Dostawcy}

Dekompozycja:

  • DostawaProdukt (ID_Dostawy, ID_Produktu, Cena) – który produkt w której dostawie
  • DostawaDostawca (ID_Dostawy, ID_Dostawcy, Data) – kto dostarcza daną dostawę
  • ProduktDostawca (ID_Produktu, ID_Dostawcy) – który produkt może dostarczać który dostawca

Każda tabela w 5NF.

Trzy podzbiory JD → trzy nowe tabele. Każda przechowuje jeden aspekt relacji. 5NF spełniona.
Ćwiczenie 2 – dekompozycja na trzy tabele

Drugie ćwiczenie wymaga zaprojektowania dekompozycji tabeli DostawyProduktyDostawcy do piątej postaci normalnej, zakładając że zależność złączeniowa jest spełniona. Na podstawie analizy JD *{ID_Dostawy, ID_Produktu}, {ID_Dostawy, ID_Dostawcy, Data}, {ID_Produktu, ID_Dostawcy} należy utworzyć trzy osobne tabele, z których każda będzie przechowywała jeden aspekt relacji między encjami. Pierwsza tabela DostawaProdukt zawierać będzie pary (ID_Dostawy, ID_Produktu) wraz z atrybutem Cena, który jest funkcyjnie zależny od tej właśnie pary.

Druga tabela DostawaDostawca przechowuje informację o tym, który dostawca realizuje daną dostawę, wraz z datą dostawy. Jej klucz główny stanowi para (ID_Dostawy, ID_Dostawcy), a atrybut Data jest od niej w pełni zależny funkcyjnie. Trzecia tabela ProduktDostawca zawiera dane o tym, który produkt może być dostarczany przez którego dostawcę, z kluczem złożonym (ID_Produktu, ID_Dostawcy). Każda z tych tabel ma prostą strukturę dwuatrybutowego klucza głównego i co najwyżej jeden dodatkowy atrybut.

Po zakończeniu dekompozycji każda z trzech nowych tabel automatycznie znajduje się w 5NF, ponieważ ma tylko jeden klucz kandydujący i żadnych złożonych zależności między atrybutami. Wszystkie potencjalne JD w tych tabelach są trywialne i wynikają bezpośrednio z kluczy. Należy również pamiętać o dodaniu kluczy obcych łączących nowe tabele z istniejącymi tabelami słownikowymi, takimi jak Produkty i Dostawcy, co zapewni integralność referencyjną całego schematu.

28/60Ćwiczenie 3: czy to narusza 5NF?

Tabela StudenciWykladowcyPrzedmioty

Tabela StudenciWykladowcyPrzedmioty: (ID_Studenta, ID_Wykladowcy, ID_Przedmiotu, Ocena)

Założenie: każdy wykładowca uczy wiele przedmiotów, każdy student może mieć zajęcia z wieloma wykładowcami.

JD: *{ID_Studenta, ID_Przedmiotu}, {ID_Studenta, ID_Wykladowcy}, {ID_Wykladowcy, ID_Przedmiotu}

  • Czy JD jest spełniona? TYLKO jeśli każda kombinacja (student, wykładowca, przedmiot) istnieje
  • W praktyce: NIE – student ma ocenę tylko z konkretnego przedmiotu u konkretnego wykładowcy
  • Wniosek: JD nie jest spełniona → tabela może być w 5NF (pomimo teoretycznej JD)
JD istnieje w teorii, ale w praktyce nie jest spełniona (bo Ocena wymusza konkretne pary). Tabela jest w 5NF.
Ćwiczenie 3 – tabela StudenciWykladowcyPrzedmioty

Trzecie ćwiczenie analizuje tabelę StudenciWykladowcyPrzedmioty o atrybutach ID_Studenta, ID_Wykladowcy, ID_Przedmiotu oraz Ocena. Klucz główny tej tabeli jest złożony ze wszystkich trzech atrybutów identyfikacyjnych, ponieważ ocena jest przypisana do konkretnej kombinacji studenta, wykładowcy i przedmiotu. Potencjalna JD *{ID_Studenta, ID_Przedmiotu}, {ID_Studenta, ID_Wykladowcy}, {ID_Wykladowcy, ID_Przedmiotu} istnieje w teorii, ale jej spełnienie zależy od konkretnych reguł biznesowych obowiązujących w systemie.

Kluczowym czynnikiem decydującym o spełnieniu JD jest obecność atrybutu Ocena, który zależy od całej trójki encji. W praktyce oznacza to, że nie wszystkie kombinacje studenta, wykładowcy i przedmiotu są możliwe, ponieważ ocena musi być wystawiona przez konkretnego wykładowcę za konkretny przedmiot dla konkretnego studenta. Nawet jeśli w projekcjach binarnych istnieją wszystkie pary, trójka (student, wykładowca, przedmiot) może nie istnieć w oryginalnej tabeli, jeśli ocena nie została jeszcze wystawiona lub taka kombinacja nie jest dozwolona przez regulamin studiów.

Wniosek z tego ćwiczenia jest następujący: mimo że JD istnieje w teorii, w praktyce nie jest spełniona ze względu na atrybut Ocena, który blokuje możliwość dowolnych kombinacji. Tabela pozostaje zatem w 5NF, ponieważ pomimo istnienia JD, nie jest ona spełniona przez dane, a zatem dekompozycja nie jest wymagana. To ćwiczenie doskonale ilustruje, jak ważne jest odróżnienie teoretycznej możliwości wystąpienia JD od jej faktycznego spełnienia w konkretnym systemie.

29/60Scenariusz: system rekomendacji w bibliotece

System rekomendacji – nowa funkcjonalność

  • W naszej bibliotece: bibliotekarze polecają książki autorów czytelnikom
  • Chcemy rejestrować: który bibliotekarz poleca którą książkę którego autora
  • Tabela Rekomendacje: (ISBN, Autor, ID_Bibliotekarza)
  • Reguły biznesowe:
  • - Bibliotekarz może polecać dowolną książkę (niezależnie od autora)
  • - Bibliotekarz może polecać dowolnego autora (niezależnie od książki)
  • - Książka ma autora (oczywiste)
  • Problem: czy te trzy fakty są niezależne?
System rekomendacji: bibliotekarze polecają książki autorów. Trzy encje, jedna tabela. Czy to JD?
System rekomendacji – trzy encje: książka, autor, bibliotekarz

W naszej przykładowej bibliotece wprowadzamy nowy system rekomendacji, który ma umożliwić bibliotekarzom polecanie czytelnikom konkretnych książek i autorów. System ten wymaga przechowywania informacji o tym, który bibliotekarz poleca którą książkę którego autora, co prowadzi do utworzenia tabeli Rekomendacje o trzech atrybutach: ISBN, Autor oraz ID_Bibliotekarza. Każdy wiersz w tej tabeli interpretujemy jako stwierdzenie, że dany bibliotekarz poleca konkretną książkę napisaną przez konkretnego autora.

Reguły biznesowe w tym systemie są celowo zaprojektowane tak, aby dopuszczać wysoki stopień swobody: każdy bibliotekarz może polecać dowolną książkę bez względu na jej autora, a także może polecać dowolnego autora bez względu na konkretną książkę. Oznacza to, że relacje binarne między parami atrybutów są w pełni niezależne, co stwarza idealne warunki do wystąpienia zależności złączeniowej. Jeśli reguły te są w pełni przestrzegane, każda kombinacja ISBN, autora i bibliotekarza powinna być dozwolona, o ile tylko istnieją odpowiednie związki między parami.

Scenariusz ten został celnie dobrany do zilustrowania mechanizmu JD, ponieważ pokazuje, jak pozornie nieszkodliwy system rekomendacji może ukrywać zależność złączeniową. W praktyce rzadko zdarza się, aby reguły biznesowe pozwalały na taką dowolność, ale właśnie dlatego ten przykład jest tak pouczający. Pokazuje on, że nawet w prostych strukturach trójskładnikowych mogą istnieć złożone zależności wymagające analizy w kontekście 5NF, a ich wykrycie wymaga starannego zbadania reguł biznesowych i danych.

30/60Analiza zależności w Rekomendacje

Analiza JD w tabeli Rekomendacje

  • Atrybuty: ISBN, Autor, ID_Bibliotekarza
  • Klucz: (ISBN, Autor, ID_Bibliotekarza) – wszystkie trzy kolumny
  • Założenie: wszystkie pary są niezależne
  • - (ISBN, Autor) – książka ma autora (fakt oczywisty)
  • - (ISBN, ID_Bib) – bibliotekarz poleca książkę
  • - (Autor, ID_Bib) – bibliotekarz poleca autora
  • Jeśli te trzy pary są niezależne, to JD *{ISBN, Autor}, {ISBN, ID_Bib}, {Autor, ID_Bib} może być spełniona
  • Jeśli JD jest spełniona: tabelę można rozłożyć na 3 mniejsze
Trzy pary, trzy relacje binarne. Czy są niezależne? Jeśli tak – JD istnieje i trzeba rozłożyć.
Analiza zależności – trzy pary atrybutów

Analiza zależności w tabeli Rekomendacje rozpoczyna się od identyfikacji wszystkich możliwych par atrybutów i określenia, czy między nimi zachodzą jakiekolwiek ograniczenia. Mamy trzy atrybuty: ISBN, Autor oraz ID_Bibliotekarza, które tworzą trzy pary: (ISBN, Autor), (ISBN, ID_Bibliotekarza) oraz (Autor, ID_Bibliotekarza). Każda z tych par reprezentuje inną relację binarną: para (ISBN, Autor) oznacza, że dana książka ma określonego autora, para (ISBN, ID_Bibliotekarza) oznacza polecenie książki przez bibliotekarza, a para (Autor, ID_Bibliotekarza) oznacza polecenie autora przez bibliotekarza.

Z punktu widzenia teorii normalizacji, kluczowe pytanie dotyczy niezależności tych trzech par. Jeśli każda para może występować niezależnie od pozostałych, to znaczy, że wartości w jednej parze nie determinują wartości w trzecim atrybucie, wówczas mamy do czynienia z potencjalną JD. W szczególności, jeśli dla danego ISBN istnieje autor A i bibliotekarz B, a dla tego samego autora A istnieje związek z bibliotekarzem B, to czy musi istnieć wiersz łączący wszystkie trzy wartości w jednym rekordzie?

Odpowiedź na to pytanie zależy wyłącznie od reguł biznesowych systemu. Jeśli system biblioteczny działa według zasady, że bibliotekarz polecający książkę i autora automatycznie poleca tę książkę tego autora, to JD jest spełniona. Jeśli jednak bibliotekarz może selektywnie polecać książki niezależnie od autorów, mimo że poleca zarówno daną książkę, jak i danego autora, to JD nie zachodzi. Ta subtelna różnica w regułach biznesowych decyduje o tym, czy tabela wymaga dekompozycji do 5NF.

31/60Przykładowe dane w Rekomendacje

Trzy wiersze – test JD

ISBNAutorID_Bibliotekarza
978-83-123-4567-1Stefan Żeromski1
978-83-123-4567-1Bolesław Prus2
978-83-123-4567-2Stefan Żeromski2

Tylko 3 wiersze – czy JD jest spełniona?

Sprawdźmy pary:

  • (ISBN1, Żeromski) ✔, (ISBN1, Prus) ✔, (ISBN2, Żeromski) ✔
  • (ISBN1, Bib1) ✔, (ISBN1, Bib2) ✔, (ISBN2, Bib2) ✔
  • (Żeromski, Bib1) ✔, (Prus, Bib2) ✔, (Żeromski, Bib2) ✔

Czy istnieje (ISBN1, Żeromski, Bib2)?

  • Wszystkie pary istnieją: (ISBN1, Żeromski), (ISBN1, Bib2), (Żeromski, Bib2)
  • Ale w danych: NIE MA tego wiersza!

JD NIE jest spełniona.

Wszystkie pary istnieją, ale trójka (ISBN1, Żeromski, Bib2) nie istnieje. JD nie jest spełniona – tabeli nie da się rozłożyć.
Tabela Rekomendacje – trzy wiersze danych

Przykładowe dane w tabeli Rekomendacje zostały dobrane tak, aby zilustrować sytuację, w której JD nie jest spełniona, mimo że wszystkie pary atrybutów są obecne w odpowiednich projekcjach. Tabela zawiera trzy wiersze: pierwszy łączy ISBN1 z autorem Żeromskim i bibliotekarzem 1, drugi łączy ISBN1 z autorem Prusem i bibliotekarzem 2, a trzeci łączy ISBN2 z autorem Żeromskim i bibliotekarzem 2. W tych trzech wierszach każda z trzech możliwych par atrybutów występuje co najmniej raz, ale brakuje jednej konkretnej trójki.

Konkretnie, para (ISBN1, Żeromski) istnieje w wierszu pierwszym, para (ISBN1, bibliotekarz 2) istnieje w wierszu drugim, a para (Żeromski, bibliotekarz 2) istnieje w wierszu trzecim. Gdyby JD *{ISBN, Autor}, {ISBN, ID_Bibliotekarza}, {Autor, ID_Bibliotekarza} była spełniona, w tabeli musiałby istnieć wiersz (ISBN1, Żeromski, bibliotekarz 2), ponieważ wszystkie trzy składające się na niego pary są obecne w projekcjach. Taki wiersz jednak nie istnieje, co stanowi dowód na to, że JD nie jest spełniona.

Brak tego wiersza ma konkretne uzasadnienie biznesowe: bibliotekarz 2 nie poleca książki ISBN1 w kontekście autora Żeromskiego, mimo że poleca samego Żeromskiego w książce ISBN2 oraz poleca książkę ISBN1 w kontekście autora Prusa. Ta selektywność poleceń jest w pełni uzasadniona z punktu widzenia reguł biznesowych i pokazuje, że nie wszystkie kombinacje trójek muszą być dozwolone. W rezultacie tabela pozostaje w 5NF, ponieważ JD nie jest spełniona, a dekompozycja nie jest wymagana.

32/60Co oznacza brak JD w praktyce?

Brak JD = konkretna reguła biznesowa

Brak (ISBN1, Żeromski, Bib2) oznacza: 'Bib2 nie poleca Żeromskiego w książce ISBN1'.

Mimo że:

  • Bib2 poleca książkę ISBN1 (z Prusem)
  • Bib2 poleca Żeromskiego (w książce ISBN2)
  • Żeromski jest autorem ISBN1

To Bib2 NIE poleca Żeromskiego w ISBN1.

To jest konkretna reguła biznesowa – nie wszystkie kombinacje są dozwolone.

W 5NF: jeśli JD nie jest spełniona, tabela może być w 5NF (JD nie wynika z danych).

Brak JD = konkretna reguła biznesowa: 'Bib2 nie poleca Żeromskiego w tej konkretnej książce'. To ma sens biznesowy – 5NF nie wymaga rozkładu.
Brak JD – konkretna reguła biznesowa

Brak spełnienia zależności złączeniowej w praktyce oznacza, że w systemie obowiązują konkretne reguły biznesowe ograniczające dozwolone kombinacje wartości atrybutów. W przypadku tabeli Rekomendacje, brak wiersza (ISBN1, Żeromski, bibliotekarz 2) wskazuje na to, że bibliotekarz 2 nie poleca Żeromskiego w tej konkretnej książce. Decyzja ta może wynikać z subiektywnej oceny bibliotekarza, który uważa, że twórczość Żeromskiego jest wartościowa, ale konkretna książka ISBN1 nie zasługuje na polecenie w zestawieniu z tym autorem.

Z punktu widzenia integralności danych, brak JD jest zjawiskiem pożądanym, ponieważ odzwierciedla rzeczywiste reguły biznesowe i zapobiega powstawaniu fałszywych skojarzeń między encjami. Gdybyśmy mechanicznie rozłożyli tabelę na trzy projekcje binarne, a następnie je złączyli, otrzymalibyśmy dodatkowy wiersz (ISBN1, Żeromski, bibliotekarz 2), który nie występuje w rzeczywistych danych. Taki fałszywy wiersz stanowiłby naruszenie integralności systemu, sugerując polecenie, które w rzeczywistości nie miało miejsca.

Wniosek praktyczny jest następujący: dekompozycję do 5NF należy wykonywać wyłącznie wtedy, gdy JD jest faktycznie spełniona przez dane i reguły biznesowe. Jeśli JD nie jest spełniona, oznacza to, że system wymaga przechowywania wszystkich trzech atrybutów razem w jednej tabeli, ponieważ tylko w ten sposób można odzwierciedlić istniejące ograniczenia. Próba dekompozycji w takiej sytuacji prowadzi do utraty informacji o rzeczywistych ograniczeniach biznesowych i generowania nieprawdziwych danych.

33/60Kiedy JD JEST spełniona?

JD spełniona – wszystkie kombinacje dozwolone

Jeśli reguły biznesowe mówią: 'każda para może wystąpić niezależnie'.

Czyli: jeśli bibliotekarz poleca książkę i poleca autora, to automatycznie poleca tę książkę tego autora.

Wtedy JD jest spełniona – i tabelę TRZEBA rozłożyć do 5NF.

Przykład danych z JD spełnioną:

  • (ISBN1, Żeromski, Bib1)
  • (ISBN1, Prus, Bib2)
  • (ISBN2, Żeromski, Bib2)
  • (ISBN1, Żeromski, Bib2) – WYMAGANY przez JD!

Jeśli dodamy ten wiersz – JD spełniona, tabelę można rozłożyć.

Jeśli reguły mówią 'zawsze możliwe' – JD jest spełniona. Wtedy: 3 tabele zamiast 1. Czysto i prosto.
JD spełniona – wszystkie cztery kombinacje istnieją

Zależność złączeniowa jest spełniona, gdy reguły biznesowe dopuszczają wszystkie możliwe kombinacje wartości atrybutów wynikające z istniejących par. W kontekście bibliotecznym oznacza to, że jeśli bibliotekarz poleca daną książkę i poleca danego autora, to automatycznie poleca tę książkę tego autora. Taka sytuacja ma miejsce, gdy system rekomendacji działa według zasady pełnej kompozycyjności: każda kombinacja encji, która jest dozwolona na poziomie par, jest również dozwolona na poziomie trójek.

W praktyce spełnienie JD oznacza, że dane w tabeli muszą zawierać wszystkie kombinacje wynikające z projekcji binarnych. Jeśli w projekcji (ISBN, Autor) mamy parę (ISBN1, Żeromski), w projekcji (ISBN, ID_Bibliotekarza) mamy parę (ISBN1, bibliotekarz 2), a w projekcji (Autor, ID_Bibliotekarza) mamy parę (Żeromski, bibliotekarz 2), to w pełnej tabeli musi istnieć wiersz (ISBN1, Żeromski, bibliotekarz 2). Brak tego wiersza oznacza niespełnienie JD.

Aby JD była spełniona, muszą być zatem spełnione dwa warunki: po pierwsze, reguły biznesowe nie mogą nakładać żadnych ograniczeń na kombinacje trójek poza tymi, które wynikają z par, a po drugie, dane muszą faktycznie zawierać wszystkie wymagane kombinacje. Spełnienie tych warunków jest w praktyce bardzo rzadkie, ponieważ większość systemów ma bogate reguły biznesowe, które naturalnie ograniczają dozwolone kombinacje nawet na poziomie trójek.

34/60Porównanie: JD spełniona vs nie spełniona

Porównanie dwóch scenariuszy

AspektJD nie spełnionaJD spełniona
Reguła biznesowaKonkretne ograniczeniaWszystkie kombinacje dozwolone
Liczba wierszyN (tylko istniejące)Wszystkie kombinacje
Można rozłożyć?NIETAK
5NFSpełniona (automatycznie)Wymaga dekompozycji
W praktyceBardzo częsteBardzo rzadkie
JD spełniona = rzadkość. W praktyce: prawie zawsze JD nie jest spełniona, więc 5NF jest automatycznie spełniona.
Porównanie JD spełniona vs nie spełniona

Porównanie dwóch scenariuszy, w których JD jest spełniona i nie jest spełniona, pozwala na lepsze zrozumienie praktycznych implikacji piątej postaci normalnej. W scenariuszu, gdzie JD nie jest spełniona, w tabeli brakuje pewnych kombinacji trójek, mimo że wszystkie pary istnieją w odpowiednich projekcjach. Taka sytuacja odzwierciedla istnienie konkretnych reguł biznesowych, które ograniczają dozwolone kombinacje, a tabela pozostaje w 5NF bez konieczności dekompozycji.

W scenariuszu, gdzie JD jest spełniona, wszystkie kombinacje trójek wynikające z par są obecne w tabeli, co oznacza, że reguły biznesowe dopuszczają pełną dowolność kombinacji. W tym przypadku tabela nie znajduje się w 5NF i wymaga dekompozycji na trzy mniejsze tabele binarne. Liczba wierszy w oryginalnej tabeli jest wtedy dokładnie równa liczbie wierszy powstałej ze złączenia trzech projekcji, co potwierdza bezstratność dekompozycji.

Z praktycznego punktu widzenia, różnica między tymi dwoma scenariuszami ma kluczowe znaczenie dla integralności danych. Jeśli JD nie jest spełniona, dekompozycja prowadzi do utraty informacji o rzeczywistych ograniczeniach biznesowych i generowania fałszywych wierszy. Jeśli JD jest spełniona, dekompozycja jest bezpieczna i prowadzi do czystszej struktury danych. Dlatego tak ważne jest wykonanie testu JD przed podjęciem decyzji o dekompozycji, ponieważ błędna ocena może prowadzić do poważnych problemów z integralnością.

35/60Wizualizacja: rozkład tabeli z JD spełnioną

Dekompozycja na trzy tabele binarne

Tabela Rekomendacje z 4 wierszami (JD spełniona):

  • (ISBN1, Żeromski, Bib1), (ISBN1, Prus, Bib2), (ISBN2, Żeromski, Bib2), (ISBN1, Żeromski, Bib2)

Rozkład na 3 tabele:

  • KsiazkiAutorzy: (ISBN1, Żeromski), (ISBN1, Prus), (ISBN2, Żeromski) – 3 wiersze
  • KsiazkiBib: (ISBN1, Bib1), (ISBN1, Bib2), (ISBN2, Bib2) – 3 wiersze
  • AutorzyBib: (Żeromski, Bib1), (Prus, Bib2), (Żeromski, Bib2) – 3 wiersze

Złączenie tych 3 tabel daje 4 wiersze = oryginalna tabela. Bezstratne!

3 tabele × 3 wiersze = 9 wierszy (teoretycznie). Ale złączenie daje tylko 4 wiersze – dokładnie tyle, ile w oryginale. Bezstratne.
Wizualizacja rozkładu – trzy tabele binarne

Wizualizacja rozkładu tabeli z JD spełnioną na trzy tabele binarne pomaga zrozumieć, jak działa mechanizm dekompozycji w praktyce. Załóżmy, że tabela Rekomendacje zawiera cztery wiersze spełniające JD, a więc każda kombinacja par znajduje odzwierciedlenie w pełnej trójce. Projekcja na atrybuty (ISBN, Autor) daje trzy pary: (ISBN1, Żeromski), (ISBN1, Prus) i (ISBN2, Żeromski). Projekcja na (ISBN, ID_Bibliotekarza) również daje trzy pary: (ISBN1, bibliotekarz 1), (ISBN1, bibliotekarz 2) i (ISBN2, bibliotekarz 2).

Projekcja na (Autor, ID_Bibliotekarza) także zawiera trzy pary: (Żeromski, bibliotekarz 1), (Prus, bibliotekarz 2) i (Żeromski, bibliotekarz 2). Łącznie trzy projekcje zawierają dziewięć wierszy, podczas gdy oryginalna tabela miała tylko cztery wiersze. Złączenie tych trzech projekcji daje w wyniku dokładnie cztery wiersze, które są identyczne z wierszami oryginalnej tabeli. To potwierdza, że dekompozycja jest bezstratna i że JD jest rzeczywiście spełniona.

Wizualizacja ta pokazuje również, dlaczego dekompozycja do 5NF prowadzi do zwiększenia liczby przechowywanych wierszy z czterech do dziewięciu, ale jednocześnie eliminuje ukryte zależności między atrybutami. Każdy fakt jest teraz przechowywany w jednym miejscu: informacja o autorstwie książki znajduje się w tabeli KsiazkiAutorzy, informacja o poleceniu książki przez bibliotekarza w tabeli KsiazkiBibliotekarze, a informacja o poleceniu autora przez bibliotekarza w tabeli AutorzyBibliotekarze. Taka struktura jest bardziej elastyczna i odporna na anomalie.

36/605NF w kontekście całego schematu biblioteki

Rozszerzenie schematu o 5NF

Po dodaniu 5NF (jeśli JD jest spełniona):

  • Zamiast 1 tabeli Rekomendacje – 3 tabele:
  • - KsiazkiAutorzy (ISBN, Autor)
  • - KsiazkiBibliotekarze (ISBN, ID_Bib)
  • - AutorzyBibliotekarze (Autor, ID_Bib)
  • Łącznie: 8 + 2 nowe = 10 tabel (jeśli KsiazkiAutorzy i KsiazkiBibliotekarze już nie istnieją gdzie indziej)

W praktyce: KsiazkiAutorzy może zastąpić istniejącą strukturę.

5NF często 'odkrywa' brakujące tabele, które powinny istnieć.

5NF często odkrywa brakujące związki między encjami. 'Odkrywa' tabele, które powinny być w schemacie od początku.
Schemat biblioteki po dodaniu 5NF – 10 tabel

Po dodaniu 5NF do naszego schematu bibliotecznego, liczba tabel może wzrosnąć z ośmiu do dziesięciu, w zależności od tego, czy niektóre z projekcji binarnych już istnieją w schemacie. Na przykład tabela KsiazkiAutorzy może już istnieć, jeśli wcześniej znormalizowaliśmy dane o autorstwie książek zgodnie z wymaganiami 3NF lub BCNF. W takim przypadku 5NF nie dodaje nowej tabeli, a jedynie wykorzystuje już istniejącą strukturę do przechowywania odpowiednich danych.

W kontekście całego schematu, 5NF często odkrywa brakujące tabele, które powinny były znaleźć się w bazie danych już na etapie projektowania konceptualnego. Jeśli podczas modelowania związku między książkami, autorami i bibliotekarzami pominięto fakt, że każda para tych encji tworzy osobną relację, to 5NF wymusi dodanie odpowiednich tabel. W tym sensie 5NF pełni funkcję weryfikatora poprawności modelu związków encji, ujawniając ukryte powiązania.

Warto zauważyć, że 5NF nie dodaje tabel arbitralnie, ale jedynie wtedy, gdy istnieje ku temu uzasadnienie w postaci spełnionej JD. Jeśli reguły biznesowe nie dopuszczają wszystkich kombinacji, 5NF jest automatycznie spełniona i nie wymaga modyfikacji schematu. Dlatego też proces normalizacji do 5NF jest selektywny i dotyczy wyłącznie tych relacji, w których faktycznie występują zależności złączeniowe niewynikające z kluczy kandydujących.

37/60Czy 5NF jest zawsze potrzebna?

W praktyce: PRAWIE NIGDY

5NF jest potrzebna tylko przy:

  • Relacjach trójskładnikowych (lub więcej)
  • Gdzie wszystkie pary są niezależne
  • Gdzie JD jest spełniona przez reguły biznesowe
  • Większość systemów: 3NF/BCNF w zupełności wystarcza

5NF to głównie wiedza akademicka – warto znać, rzadko stosować.

5NF jest jak instrukcja obsługi pralki po japońsku – warto wiedzieć, że istnieje, ale w praktyce używasz polskiej wersji (3NF).
Czy 5NF jest potrzebna? – rzadko, ale warto znać

Piąta postać normalna nie jest zawsze potrzebna, a w praktyce większość systemów bazodanowych działa poprawnie i efektywnie bez jej stosowania. Decyzja o zastosowaniu 5NF powinna być podejmowana na podstawie analizy konkretnych wymagań projektowych, a nie jako automatyczny krok w procesie normalizacji. Większość tabel w rzeczywistych systemach ma prostą strukturę z jednym kluczem głównym i kilkoma atrybutami, co sprawia, że 5NF jest spełniona automatycznie bez konieczności jakichkolwiek działań.

Warunkiem koniecznym do rozważenia 5NF jest obecność relacji trójskładnikowej lub wyższego rzędu, w której wszystkie pary atrybutów są od siebie niezależne. Jeśli taka relacja występuje w systemie, należy zbadać, czy JD jest spełniona przez reguły biznesowe i dane. Jeśli tak, wówczas 5NF wymaga dekompozycji w celu wyeliminowania ukrytej zależności. Jeśli nie, tabela pozostaje w 5NF i nie wymaga modyfikacji.

W praktyce inżynierskiej przyjmuje się, że zatrzymanie na trzeciej postaci normalnej jest optymalnym rozwiązaniem dla większości systemów produkcyjnych. BCNF i 4NF są stosowane w specyficznych sytuacjach, a 5NF pozostaje głównie w sferze akademickiej. Mimo to znajomość 5NF jest ważna, ponieważ pozwala projektantowi na pełne zrozumienie teoretycznych podstaw normalizacji i świadome podejmowanie decyzji o tym, kiedy proces normalizacji można zakończyć.

38/60Ćwiczenie: znajdź JD w podanej tabeli

Tabela FakturyPozycjeDostawy

Tabela FakturyPozycjeDostawy: (ID_Faktury, ID_Pozycji, ID_Dostawy, Kwota)

Założenie:

  • Faktura zawiera wiele pozycji
  • Dostawa zawiera wiele pozycji
  • Faktura może być związana z wieloma dostawami

JD: *{ID_Faktury, ID_Pozycji}, {ID_Faktury, ID_Dostawy}, {ID_Pozycji, ID_Dostawy}

Pytania:

  • Czy JD jest spełniona? Zależy od reguł biznesowych
  • Czy tabela jest w 5NF? Jeśli JD spełniona → NIE. Jeśli nie → TAK.
  • Zaprojektuj dekompozycję
Ćwiczenie: faktury, pozycje, dostawy – trzy encje. JD *{Faktura, Pozycja}, {Faktura, Dostawa}, {Pozycja, Dostawa}. Czy wszystkie kombinacje są dozwolone?
Ćwiczenie – tabela FakturyPozycjeDostawy

W tym ćwiczeniu analizujemy tabelę FakturyPozycjeDostawy o atrybutach ID_Faktury, ID_Pozycji, ID_Dostawy oraz Kwota. Klucz główny tabeli stanowi para (ID_Faktury, ID_Pozycji), która jednoznacznie identyfikuje każdą pozycję na fakturze. Potencjalna JD, którą należy zbadać, to *{ID_Faktury, ID_Pozycji}, {ID_Faktury, ID_Dostawy}, {ID_Pozycji, ID_Dostawy}. Celem ćwiczenia jest ustalenie, czy ta JD wynika z kluczy kandydujących i czy jest spełniona przez dane.

Pierwszy podzbiór JD, {ID_Faktury, ID_Pozycji}, jest dokładnie równy kluczowi głównemu, co oznacza, że ta część JD wynika z kluczy kandydujących. Jednak pozostałe dwa podzbiory nie zawierają klucza, a zatem cała JD nie wynika automatycznie z kluczy. W drugim kroku należy sprawdzić, czy JD jest spełniona przez reguły biznesowe: jeśli każda faktura może być związana z wieloma dostawami, a każda pozycja może pochodzić z różnych dostaw, to wszystkie kombinacje par są dozwolone i JD jest spełniona.

W praktyce spełnienie JD w tej tabeli zależy od tego, czy system dopuszcza sytuację, w której ta sama pozycja na fakturze może pochodzić z różnych dostaw w zależności od konkretnej faktury. Jeśli tak, to dla każdej pary faktura-pozycja, faktura-dostawa i pozycja-dostawa musi istnieć odpowiadająca im trójka w oryginalnej tabeli. W przeciwnym razie JD nie jest spełniona i tabela pozostaje w 5NF. To ćwiczenie pokazuje, jak ważne jest zrozumienie reguł biznesowych przed podjęciem decyzji o dekompozycji.

39/60Ćwiczenie: zaprojektuj bazę w 5NF

System recept – lekarze, pacjenci, leki

System: lekarze przepisują leki pacjentom w określonych dawkach.

Tabela Recepty: (ID_Lekarza, ID_Pacjenta, ID_Leku, Dawka, Data)

Założenie:

  • Lekarz może przepisać każdy lek każdemu pacjentowi
  • Dawka zależy od (Lekarz, Pacjent, Lek)

JD: *{ID_Lekarza, ID_Pacjenta}, {ID_Lekarza, ID_Leku}, {ID_Pacjenta, ID_Leku}

  • Czy JD spełniona? NIE – Dawka zależy od całej trójki, więc nie wszystkie kombinacje są możliwe
  • Tabela jest w 5NF (JD nie spełniona)
Dawka zależy od całej trójki – więc JD nie jest spełniona. Mimo teoretycznej JD, tabela jest w 5NF. Dawka 'blokuje' niechciane kombinacje.
Ćwiczenie – system recept z dawką

W tym ćwiczeniu projektujemy system recept, w którym lekarze przepisują leki pacjentom w określonych dawkach. Tabela Recepty zawiera atrybuty ID_Lekarza, ID_Pacjenta, ID_Leku, Dawka oraz Data, a klucz główny jest złożony ze wszystkich atrybutów identyfikacyjnych, ponieważ dawka leku zależy od konkretnej kombinacji lekarza, pacjenta i leku. Potencjalna JD, którą należy rozważyć, to *{ID_Lekarza, ID_Pacjenta}, {ID_Lekarza, ID_Leku}, {ID_Pacjenta, ID_Leku}.

Kluczowym czynnikiem decydującym o tym, czy JD jest spełniona, jest atrybut Dawka, który zależy od całej trójki encji. W praktyce oznacza to, że nie wszystkie kombinacje lekarza, pacjenta i leku są dozwolone, ponieważ dawka musi być przepisana przez konkretnego lekarza dla konkretnego pacjenta i konkretnego leku. Nawet jeśli w projekcjach binarnych istnieją wszystkie pary, trójka może nie istnieć w oryginalnej tabeli, jeśli taka kombinacja nie została zrealizowana w postaci recepty.

Wniosek z tego ćwiczenia jest analogiczny do poprzednich: mimo że JD istnieje w teorii, nie jest spełniona w praktyce ze względu na atrybut Dawka, który blokuje możliwość dowolnych kombinacji. Tabela pozostaje zatem w 5NF, ponieważ pomimo istnienia JD, nie jest ona spełniona przez dane. To ćwiczenie dodatkowo podkreśla, że obecność dodatkowego atrybutu opisującego związek między encjami często uniemożliwia spełnienie JD i czyni 5NF automatycznie zachowaną.

40/60Podsumowanie: kiedy stosować 5NF?

Kryteria stosowania 5NF

  • Gdy masz relację trójskładnikową (lub więcej)
  • Gdy wszystkie pary są niezależne (reguły biznesowe nie ograniczają kombinacji)
  • Gdy JD jest spełniona (wszystkie kombinacje istnieją lub są dozwolone)
  • Gdy rozkład na mniejsze tabele nie pogarsza wydajności
  • W praktyce: NIGDY (prawie) – ale warto znać teorię

Pamiętaj: jeśli masz wątpliwości – sprawdź JD. Jeśli JD nie jest spełniona – 5NF jest OK.

5NF stosuj, gdy: 1) masz relację 3-składnikową, 2) wszystkie pary niezależne, 3) JD spełniona. W praktyce: 1 na 100000 tabel.
Kiedy stosować 5NF – schemat decyzyjny

Podsumowując dyskusję o praktycznym zastosowaniu piątej postaci normalnej, można sformułować trzy konkretne warunki, które muszą być spełnione jednocześnie, aby dekompozycja do 5NF była uzasadniona. Po pierwsze, tabela musi modelować relację trójskładnikową lub wyższego rzędu, co oznacza, że zawiera co najmniej trzy atrybuty powiązane ze sobą w sposób niezależny. Po drugie, wszystkie pary atrybutów muszą być od siebie niezależne, co oznacza, że wartości w jednej parze nie determinują wartości w trzecim atrybucie.

Po trzecie, zależność złączeniowa musi być faktycznie spełniona przez dane i reguły biznesowe, co można zweryfikować za pomocą testu złączenia projekcji. Jeśli wszystkie trzy warunki są spełnione, 5NF wymaga dekompozycji na osobne tabele binarne. Jeśli którykolwiek z warunków nie jest spełniony, tabela znajduje się w 5NF i nie wymaga modyfikacji. W praktyce wszystkie trzy warunki są spełnione jednocześnie niezwykle rzadko, co wyjaśnia, dlaczego 5NF jest tak rzadko stosowana.

Ostateczna rekomendacja dla projektantów baz danych jest następująca: projektuj schemat w 3NF jako punkt wyjścia, a następnie rozważaj wyższe postaci normalne tylko wtedy, gdy analiza reguł biznesowych wskazuje na konkretne problemy. 5NF powinna być stosowana wyłącznie wtedy, gdy istnieją ku temu wyraźne przesłanki w postaci zidentyfikowanej i spełnionej JD. W przeciwnym razie czas poświęcony na analizę 5NF jest lepiej spożytkowany na inne aspekty projektowania systemu.

41/60Krok 1: Tworzenie tabeli potencjalnie nie w 5NF

CREATE TABLE – Rekomendacje

-- Tabela Rekomendacje – trójskładnikowa relacja
-- Potencjalnie narusza 5NF, jeśli JD jest spełniona
CREATE TABLE Rekomendacje (
    ISBN             VARCHAR(20) NOT NULL,
    Autor            VARCHAR(100) NOT NULL,
    ID_Bibliotekarza INT NOT NULL,
    PRIMARY KEY (ISBN, Autor, ID_Bibliotekarza)
);
-- Klucz: (ISBN, Autor, ID_Bib) – wszystkie trzy kolumny
-- 4NF: brak MVD (nie ma dwóch niezależnych list – są trzy wymiary)
-- 5NF: zależy od tego, czy JD *{ISBN, Autor}, {ISBN, Bib}, {Autor, Bib} jest spełniona
Tabela w 4NF, ale potencjalnie nie w 5NF. To pokazuje, że 4NF to nie koniec – JD może wymagać dalszej dekompozycji.
CREATE TABLE – Rekomendacje z kluczem złożonym

Implementację piątej postaci normalnej w systemie MariaDB rozpoczynamy od utworzenia tabeli Rekomendacje, która ma potencjał naruszania 5NF, jeśli zależność złączeniowa okaże się spełniona. Tabela ta zawiera trzy kolumny: ISBN typu VARCHAR o długości 20 znaków, Autor typu VARCHAR o długości 100 znaków oraz ID_Bibliotekarza typu INTEGER. Klucz główny jest złożony ze wszystkich trzech kolumn, co zapewnia, że każda kombinacja ISBN, autora i bibliotekarza może wystąpić w tabeli tylko raz.

Struktura tej tabeli jest zgodna z czwartą postacią normalną, ponieważ nie zawiera żadnych zależności wielowartościowych niewynikających z kluczy. Między atrybutami nie występują dwie niezależne listy, które wymagałyby rozdzielenia na osobne tabele. Jednak z punktu widzenia 5NF, tabela ta wymaga dalszej analizy, ponieważ istnieje w niej potencjalna JD *{ISBN, Autor}, {ISBN, ID_Bibliotekarza}, {Autor, ID_Bibliotekarza}, która może być spełniona w zależności od reguł biznesowych i danych.

W kodzie SQL tworzymy tabelę za pomocą polecenia CREATE TABLE, definiując wszystkie trzy kolumny jako NOT NULL ze względu na ich udział w kluczu głównym. Klauzula PRIMARY KEY zapewnia integralność wewnątrz tabeli, gwarantując, że nie pojawią się duplikaty pełnych trójek. W dalszych krokach wstawimy dane testowe i sprawdzimy, czy JD jest spełniona, co zdecyduje o konieczności dekompozycji do 5NF.

42/60Krok 2: Wstawienie danych – test JD

INSERT – dane testowe

-- Wstawienie danych – tylko 3 wiersze (JD NIE spełniona)
INSERT INTO Rekomendacje VALUES
    ('978-83-123-4567-1', 'Stefan Żeromski', 1),
    ('978-83-123-4567-1', 'Bolesław Prus', 2),
    ('978-83-123-4567-2', 'Stefan Żeromski', 2);
-- Czy JD jest spełniona? Sprawdźmy pary:
-- Para (ISBN1, Żeromski): istnieje (wiersz 1)
-- Para (ISBN1, Bib2): istnieje (wiersz 2)
-- Para (Żeromski, Bib2): istnieje (wiersz 3)
-- Ale (ISBN1, Żeromski, Bib2) NIE istnieje! → JD NIE spełniona
3 wiersze, JD nie spełniona. Tabela w 5NF. Nie trzeba rozkładać. Proste.
INSERT – trzy wiersze danych testowych

W drugim kroku implementacji wstawiamy do tabeli Rekomendacje trzy wiersze danych testowych, które mają na celu sprawdzenie, czy zależność złączeniowa jest spełniona. Pierwszy wiersz łączy książkę o numerze ISBN1 z autorem Żeromskim i bibliotekarzem 1, drugi wiersz łączy tę samą książkę ISBN1 z autorem Prusem i bibliotekarzem 2, a trzeci wiersz łączy książkę ISBN2 z autorem Żeromskim i bibliotekarzem 2. Po wstawieniu tych trzech wierszy analizujemy, jakie pary atrybutów występują w projekcjach tabeli.

W projekcji na atrybuty ISBN i Autor znajdujemy trzy pary: (ISBN1, Żeromski), (ISBN1, Prus) i (ISBN2, Żeromski). W projekcji na ISBN i ID_Bibliotekarza znajdujemy pary: (ISBN1, bibliotekarz 1), (ISBN1, bibliotekarz 2) i (ISBN2, bibliotekarz 2). W projekcji na Autor i ID_Bibliotekarza znajdujemy pary: (Żeromski, bibliotekarz 1), (Prus, bibliotekarz 2) i (Żeromski, bibliotekarz 2). Wszystkie dziewięć par jest obecnych w odpowiednich projekcjach, co oznacza, że każda para atrybutów występuje w tabeli w jakimś kontekście.

Mimo że wszystkie pary istnieją, w tabeli brakuje wiersza (ISBN1, Żeromski, bibliotekarz 2), który łączyłby wszystkie trzy pary w jedną trójkę. Oznacza to, że JD nie jest spełniona, ponieważ złączenie trzech projekcji wygeneruje dodatkowy wiersz nieobecny w oryginalnej tabeli. Wniosek z tego testu jest jednoznaczny: tabela znajduje się w 5NF i nie wymaga dekompozycji, ponieważ JD nie wynika z danych i reguł biznesowych.

43/60Krok 3: Alternatywny zestaw danych – JD spełniona

Alternatywny INSERT – JD spełniona

-- Wstawienie danych – JD spełniona (wszystkie kombinacje istnieją)
INSERT INTO Rekomendacje VALUES
    ('978-83-123-4567-1', 'Stefan Żeromski', 1),
    ('978-83-123-4567-1', 'Bolesław Prus', 2),
    ('978-83-123-4567-2', 'Stefan Żeromski', 2),
    ('978-83-123-4567-1', 'Stefan Żeromski', 2); -- !!! NOWY wiersz wymuszony przez JD
-- Teraz JD jest spełniona – wszystkie kombinacje par istnieją w trójkach
-- Tabela NIE jest w 5NF – trzeba rozłożyć!
Dodajemy (ISBN1, Żeromski, Bib2) i nagle JD jest spełniona. Tabela nie jest w 5NF. Trzeba rozłożyć na 3 tabele binarne.
Alternatywny INSERT – JD spełniona z 4 wierszami

W trzecim kroku modyfikujemy zestaw danych, dodając czwarty wiersz do tabeli Rekomendacje, który czyni zależność złączeniową spełnioną. Nowy wiersz zawiera książkę ISBN1, autora Żeromskiego oraz bibliotekarza 2, czyli dokładnie tę kombinację, której brakowało w poprzednim zestawie danych. Po dodaniu tego wiersza tabela zawiera cztery rekordy, a każda możliwa kombinacja par atrybutów znajduje odzwierciedlenie w odpowiadającej jej trójce.

Weryfikacja spełnienia JD polega na wykonaniu złączenia trzech projekcji i porównaniu wyniku z oryginalną tabelą. W tym przypadku projekcja na (ISBN, Autor) zawiera trzy pary, projekcja na (ISBN, ID_Bibliotekarza) zawiera trzy pary, a projekcja na (Autor, ID_Bibliotekarza) również zawiera trzy pary. Złączenie tych trzech projekcji daje w wyniku cztery wiersze, które są dokładnie takie same, jak wiersze w oryginalnej tabeli Rekomendacje. Oznacza to, że JD jest spełniona, a dekompozycja jest możliwa i bezpieczna.

W tej sytuacji tabela Rekomendacje nie znajduje się w 5NF, ponieważ JD *{ISBN, Autor}, {ISBN, ID_Bibliotekarza}, {Autor, ID_Bibliotekarza} jest spełniona i nie wynika z kluczy kandydujących. Konieczne jest zatem przeprowadzenie dekompozycji na trzy tabele binarne, z których każda będzie przechowywała jedną parę atrybutów. W kolejnych krokach zaimplementujemy tę dekompozycję i zweryfikujemy jej poprawność za pomocą testów SQL.

44/60Krok 4: Rozkład do 5NF – trzy tabele binarne

CREATE TABLE – trzy tabele w 5NF

-- Tabela 1: KsiazkiAutorzy – które książki mają których autorów
CREATE TABLE KsiazkiAutorzy (
    ISBN  VARCHAR(20) NOT NULL,
    Autor VARCHAR(100) NOT NULL,
    PRIMARY KEY (ISBN, Autor),
    FOREIGN KEY (ISBN) REFERENCES Ksiazki(ISBN)
);

-- Tabela 2: KsiazkiBibliotekarze – które książki polecają bibliotekarze
CREATE TABLE KsiazkiBibliotekarze (
    ISBN             VARCHAR(20) NOT NULL,
    ID_Bibliotekarza INT NOT NULL,
    PRIMARY KEY (ISBN, ID_Bibliotekarza),
    FOREIGN KEY (ISBN) REFERENCES Ksiazki(ISBN),
    FOREIGN KEY (ID_Bibliotekarza) REFERENCES Bibliotekarze(ID_Bibliotekarza)
);

-- Tabela 3: AutorzyBibliotekarze – których autorów polecają bibliotekarze
CREATE TABLE AutorzyBibliotekarze (
    Autor            VARCHAR(100) NOT NULL,
    ID_Bibliotekarza INT NOT NULL,
    PRIMARY KEY (Autor, ID_Bibliotekarza),
    FOREIGN KEY (ID_Bibliotekarza) REFERENCES Bibliotekarze(ID_Bibliotekarza)
);
-- Każda tabela ma klucz złożony z 2 kolumn + klucze obce dla integralności
-- Wszystkie tabele są w 5NF (prosty klucz, brak JD)
Jedna tabela z 3 kolumnami → trzy tabele z 2 kolumnami każda. Każda para encji w osobnej tabeli. 5NF spełniona.
CREATE TABLE – trzy tabele binarne

W czwartym kroku implementacji dokonujemy dekompozycji tabeli Rekomendacje na trzy tabele binarne, zgodnie z wymaganiami piątej postaci normalnej. Pierwsza tabela KsiazkiAutorzy zawiera kolumny ISBN i Autor z kluczem złożonym z obu atrybutów, przechowując informację o tym, którzy autorzy napisali które książki. Druga tabela KsiazkiBibliotekarze zawiera kolumny ISBN i ID_Bibliotekarza z kluczem złożonym, rejestrując, którzy bibliotekarze polecają które książki.

Trzecia tabela AutorzyBibliotekarze zawiera kolumny Autor i ID_Bibliotekarza z kluczem złożonym, przechowując informację o tym, których autorów polecają poszczególni bibliotekarze. Każda z tych tabel ma prostą strukturę z jednym kluczem kandydującym złożonym z dwóch atrybutów, co automatycznie zapewnia zgodność z 5NF. Wszystkie potencjalne JD w tych tabelach są trywialne i wynikają bezpośrednio z kluczy, ponieważ każda tabela ma tylko dwie kolumny.

W kodzie SQL definiujemy każdą tabelę za pomocą polecenia CREATE TABLE z odpowiednimi typami danych i kluczami głównymi. Należy również dodać klauzule FOREIGN KEY łączące kolumnę ISBN z tabelą Ksiazki oraz kolumnę ID_Bibliotekarza z tabelą Bibliotekarze, co zapewni integralność referencyjną w całym schemacie. Po utworzeniu tabel możemy wstawić do nich dane odpowiadające projekcjom oryginalnej tabeli Rekomendacje.

45/60Krok 5: Wstawianie danych po 5NF

INSERT – dane w trzech tabelach

-- Wstawienie danych do KsiazkiAutorzy
INSERT INTO KsiazkiAutorzy VALUES
    ('978-83-123-4567-1', 'Stefan Żeromski'),
    ('978-83-123-4567-1', 'Bolesław Prus'),
    ('978-83-123-4567-2', 'Stefan Żeromski');

-- Wstawienie danych do KsiazkiBibliotekarze
INSERT INTO KsiazkiBibliotekarze VALUES
    ('978-83-123-4567-1', 1),
    ('978-83-123-4567-1', 2),
    ('978-83-123-4567-2', 2);

-- Wstawienie danych do AutorzyBibliotekarze
INSERT INTO AutorzyBibliotekarze VALUES
    ('Stefan Żeromski', 1),
    ('Bolesław Prus', 2),
    ('Stefan Żeromski', 2);
-- Łącznie: 9 wierszy zamiast 4 (więcej, ale każdy fakt przechowywany raz)
9 wierszy zamiast 4. Więcej, ale każdy fakt jest w jednym miejscu. ISBN1 + Żeromski = jeden wiersz, nie duplikowany.
INSERT – dane w trzech tabelach po dekompozycji

Po utworzeniu trzech tabel binarnych w ramach dekompozycji do 5NF, przystępujemy do wstawienia danych, które odpowiadają projekcjom oryginalnej tabeli Rekomendacje. Do tabeli KsiazkiAutorzy wstawiamy trzy wiersze: książka ISBN1 z autorem Żeromskim, książka ISBN1 z autorem Prusem oraz książka ISBN2 z autorem Żeromskim. Do tabeli KsiazkiBibliotekarze wstawiamy również trzy wiersze: książka ISBN1 polecana przez bibliotekarza 1, książka ISBN1 polecana przez bibliotekarza 2 oraz książka ISBN2 polecana przez bibliotekarza 2.

Do tabeli AutorzyBibliotekarze wstawiamy trzy wiersze: autor Żeromski polecany przez bibliotekarza 1, autor Prus polecany przez bibliotekarza 2 oraz autor Żeromski polecany przez bibliotekarza 2. Łącznie w trzech tabelach mamy dziewięć wierszy, podczas gdy oryginalna tabela Rekomendacje zawierała cztery wiersze. Większa liczba wierszy po dekompozycji jest zjawiskiem normalnym i wynika z faktu, że każdy elementarny fakt jest teraz przechowywany w osobnej tabeli bez redundancji.

Warto zauważyć, że mimo większej łącznej liczby wierszy, każda z tabel binarnych jest prostsza i bardziej wyspecjalizowana niż oryginalna tabela trójskładnikowa. Ponadto, każdy fakt jest przechowywany dokładnie raz, co eliminuje potencjalne anomalie związane z aktualizacją danych. Na przykład informacja o tym, że bibliotekarz 2 poleca autora Żeromskiego, jest przechowywana w jednym wierszu tabeli AutorzyBibliotekarze, a nie w wielu wierszach jak w oryginalnej strukturze.

46/60Krok 6: Weryfikacja – złączenie bezstratne

SELECT – test złączenia

-- Test: czy złączenie trzech tabel daje oryginalne dane?
SELECT ka.ISBN, ka.Autor, kb.ID_Bibliotekarza
FROM KsiazkiAutorzy ka
JOIN KsiazkiBibliotekarze kb ON ka.ISBN = kb.ISBN
JOIN AutorzyBibliotekarze ab ON ka.Autor = ab.Autor
    AND kb.ID_Bibliotekarza = ab.ID_Bibliotekarza;
-- Wynik powinien być identyczny z oryginalną tabelą Rekomendacje (4 wiersze)
-- Jeśli JD jest spełniona: wynik = 4 wiersze (bezstratne)
-- Jeśli JD nie spełniona: wynik > 4 wiersze (dodatkowe, fałszywe wiersze)
Test: złącz trzy tabele. Wynik = 4 wiersze? TAK – JD spełniona. Wynik > 4? NIE – JD nie spełniona. Prosty test.
SELECT – test złączenia trzech tabel

Szósty krok implementacji polega na weryfikacji poprawności dekompozycji za pomocą testu złączenia bezstratnego. Wykonujemy zapytanie SQL, które łączy wszystkie trzy tabele binarne naturalnie za pomocą odpowiednich kluczy i porównuje wynik z oryginalną tabelą Rekomendacje. Zapytanie łączy tabelę KsiazkiAutorzy z tabelą KsiazkiBibliotekarze po atrybucie ISBN, a następnie łączy wynik z tabelą AutorzyBibliotekarze po atrybutach Autor i ID_Bibliotekarza.

Jeśli dekompozycja jest poprawna, wynik złączenia powinien zawierać dokładnie cztery wiersze, czyli tyle samo, ile zawierała oryginalna tabela Rekomendacje przed dekompozycją. W naszym przypadku, ponieważ JD była spełniona przed dekompozycją, wynik złączenia daje dokładnie cztery wiersze odpowiadające wszystkim kombinacjom trójek. Oznacza to, że dekompozycja jest bezstratna i żadne informacje nie zostały utracone podczas podziału na trzy tabele binarne.

Dla dodatkowej weryfikacji możemy również porównać liczbę wierszy za pomocą funkcji COUNT. Jeśli COUNT z złączenia trzech tabel jest równy COUNT z oryginalnej tabeli, dekompozycja jest w pełni poprawna. Jeśli natomiast COUNT z złączenia jest większy, oznacza to, że JD nie była spełniona i dekompozycja została wykonana błędnie. Ten prosty test ilościowy jest skutecznym narzędziem do automatycznej weryfikacji poprawności dekompozycji w codziennej praktyce administracji bazami danych.

47/60Krok 7: JD nie spełniona – co pokazuje złączenie?

Analiza przypadku: JD nie spełniona

-- Jeśli JD NIE jest spełniona (3 wiersze w oryginalnej tabeli):
-- Złączenie 3 tabel (z tylko istniejącymi kombinacjami) może dać DODATKOWE wiersze

-- Przykład: usuńmy (ISBN1, Żeromski, Bib2) z KsiazkiAutorzy?
-- NIE – to by zmieniło dane. JD nie spełniona oznacza, że
-- złączenie projekcji daje WIĘCEJ wierszy niż oryginał

-- W naszym przypadku (JD spełniona):
-- Złączenie = 4 wiersze = oryginalna tabela → OK
-- Gdyby JD nie była spełniona: złączenie > 4 wiersze → dekompozycja NIEMOŻLIWA
Jeśli złączenie daje WIĘCEJ wierszy – JD nie jest spełniona. Tabeli nie da się rozłożyć. Zostaje w 5NF.
JD nie spełniona – złączenie daje dodatkowe wiersze

W siódmym kroku analizujemy sytuację, w której JD nie jest spełniona, aby zrozumieć, jakie skutki dla integralności danych miałaby próba dekompozycji w takich warunkach. Gdybyśmy rozłożyli tabelę Rekomendacje zawierającą tylko trzy wiersze na trzy tabele binarne, a następnie złączyli je z powrotem, otrzymalibyśmy cztery wiersze zamiast trzech. Dodatkowy, czwarty wiersz (ISBN1, Żeromski, bibliotekarz 2) powstałby w wyniku złączenia par atrybutów, które istnieją w projekcjach, ale nie występują w oryginalnych danych.

Ten dodatkowy wiersz stanowi fałszywą informację, która sugeruje, że bibliotekarz 2 poleca Żeromskiego w książce ISBN1, podczas gdy w rzeczywistości taka rekomendacja nie istnieje. Wprowadzenie takiego fałszywego wiersza do systemu mogłoby mieć poważne konsekwencje biznesowe, ponieważ czytelnicy otrzymywaliby rekomendacje, które nie zostały faktycznie wystawione przez bibliotekarzy. To pokazuje, jak ważne jest upewnienie się, że JD jest spełniona przed przystąpieniem do dekompozycji.

W praktyce sytuacja, w której złączenie projekcji daje więcej wierszy niż oryginał, jest jednoznacznym sygnałem, że JD nie jest spełniona, a dekompozycja jest niedozwolona. W takim przypadku tabela pozostaje w 5NF i nie wymaga modyfikacji. Należy pamiętać, że 5NF nie wymaga dekompozycji wszystkich tabel, a jedynie tych, w których JD jest faktycznie spełniona. Większość tabel w rzeczywistych systemach pozostaje w 5NF bez konieczności jakichkolwiek zmian strukturalnych.

48/60Krok 8: Porównanie – JD spełniona vs nie spełniona w SQL

Test COUNT – sprawdzenie JD

-- Scenariusz A: JD nie spełniona (3 wiersze w Rekomendacje)
-- Złączenie 3 tabel daje: 4 wiersze (więcej niż 3) → JD nie spełniona
-- Wniosek: tabeli nie da się rozłożyć → 5NF spełniona

-- Scenariusz B: JD spełniona (4 wiersze w Rekomendacje)
-- Złączenie 3 tabel daje: 4 wiersze (tyle samo) → JD spełniona
-- Wniosek: tabelę można rozłożyć → 5NF wymaga dekompozycji

-- Jak sprawdzić w SQL?
SELECT COUNT(*) FROM Rekomendacje;
SELECT COUNT(*) FROM (
    SELECT ka.ISBN, ka.Autor, kb.ID_Bibliotekarza
    FROM KsiazkiAutorzy ka
    JOIN KsiazkiBibliotekarze kb ON ka.ISBN = kb.ISBN
    JOIN AutorzyBibliotekarze ab ON ka.Autor = ab.Autor
        AND kb.ID_Bibliotekarza = ab.ID_Bibliotekarza
) t;
-- Jeśli oba COUNT są równe → JD spełniona → rozkład możliwy
COUNT(*) oryginału = COUNT(*) złączenia? TAK → JD spełniona, rozkład możliwy. NIE → JD nie spełniona, tabela w 5NF.
Test COUNT – porównanie liczby wierszy

W ósmym kroku porównujemy dwa scenariusze JD spełnionej i niespełnionej za pomocą konkretnych zapytań SQL, które można wykonać w systemie MariaDB. Dla scenariusza, w którym JD nie jest spełniona, uruchamiamy zapytanie zliczające wiersze w oryginalnej tabeli Rekomendacje, a następnie zapytanie zliczające wiersze powstałe ze złączenia trzech projekcji binarnych. Jeśli wyniki COUNT są różne, oznacza to, że JD nie jest spełniona i dekompozycja jest niedozwolona.

Dla scenariusza, w którym JD jest spełniona, oba zapytania COUNT powinny zwrócić tę samą liczbę, co potwierdza możliwość bezpiecznej dekompozycji. W naszym przykładzie, gdy tabela zawiera cztery wiersze spełniające JD, złączenie projekcji również daje cztery wiersze, a oba zapytania zwracają wartość 4. Różnica w wynikach COUNT jest zatem prostym i skutecznym testem na spełnienie JD.

Porównanie to można również rozszerzyć o wizualną inspekcję wyników złączenia, co pozwala na identyfikację konkretnych fałszywych wierszy w przypadku niespełnionej JD. W praktyce zaleca się wykonywanie obu testów ilościowego COUNT oraz wizualnego SELECT przed podjęciem decyzji o dekompozycji. W systemach produkcyjnych warto również zautomatyzować ten proces poprzez utworzenie procedury składowanej, która wykonuje test JD i zwraca informację o możliwości dekompozycji.

49/60Krok 9: Zapytania po 5NF – praktyczne przykłady

Prostsze zapytania po dekompozycji

-- Znajdź wszystkich bibliotekarzy polecających Żeromskiego
-- Przed 5NF (jedna tabela):
SELECT DISTINCT ID_Bibliotekarza
FROM Rekomendacje
WHERE Autor = 'Stefan Żeromski';

-- Po 5NF (trzy tabele):
SELECT ID_Bibliotekarza
FROM AutorzyBibliotekarze
WHERE Autor = 'Stefan Żeromski';
-- Prostsze! Bez DISTINCT, bez JOIN-a!
5NF upraszcza zapytania! 'Kto poleca Żeromskiego?' → SELECT FROM AutorzyBibliotekarze. Jeden JOIN mniej.
Prostsze zapytania po 5NF

Po dekompozycji do 5NF niektóre zapytania stają się prostsze i bardziej intuicyjne, ponieważ każda tabela przechowuje jeden rodzaj faktów. Na przykład zapytanie o listę bibliotekarzy polecających konkretnego autora, takie jak Stefan Żeromski, wymaga w nowej strukturze wyłącznie odczytu z tabeli AutorzyBibliotekarze bez konieczności stosowania operatora DISTINCT czy złączeń. W oryginalnej strukturze to samo zapytanie wymagałoby odczytu z tabeli Rekomendacje i eliminacji duplikatów.

Zapytanie o książki polecane przez konkretnego bibliotekarza również staje się prostsze, ponieważ wystarczy odczytać odpowiednie wiersze z tabeli KsiazkiBibliotekarze. W oryginalnej strukturze to samo zapytanie wymagałoby odczytu z tabeli Rekomendacje i filtrowania po identyfikatorze bibliotekarza, ale wynik zawierałby również informacje o autorach, które w danym momencie mogą nie być potrzebne. Dekompozycja pozwala zatem na bardziej precyzyjne pobieranie danych.

Należy jednak pamiętać, że niektóre zapytania, które w oryginalnej strukturze były prostymi odczytami z jednej tabeli, po dekompozycji wymagają złączeń. Na przykład zapytanie o pełną informację o rekomendacji łączącej książkę, autora i bibliotekarza wymaga złączenia wszystkich trzech tabel binarnych. Jest to typowy kompromis między czystością struktury danych a wydajnością zapytań, który projektant bazy danych musi uwzględnić przy podejmowaniu decyzji o normalizacji do 5NF.

50/60Krok 10: Bardziej złożone zapytania po 5NF

JOIN dwóch tabel po dekompozycji

-- Znajdź bibliotekarzy polecających książkę nr 1 (wraz z autorem)
-- Po 5NF – potrzebny JOIN 2 tabel:
SELECT kb.ID_Bibliotekarza, ka.Autor
FROM KsiazkiBibliotekarze kb
JOIN KsiazkiAutorzy ka ON kb.ISBN = ka.ISBN
WHERE kb.ISBN = '978-83-123-4567-1';

-- Porównanie z oryginalną tabelą (przed 5NF):
SELECT ID_Bibliotekarza, Autor
FROM Rekomendacje
WHERE ISBN = '978-83-123-4567-1';
5NF = więcej tabel, ale prostsze zapytania do każdej. Każda tabela ma jeden cel – łatwo zapamiętać, gdzie są które dane.
Złożone zapytania – JOIN dwóch tabel

W dziesiątym kroku analizujemy bardziej złożone zapytania, które wymagają złączeń między tabelami po dekompozycji do 5NF. Przykładem może być zapytanie o listę bibliotekarzy polecających konkretną książkę wraz z nazwiskami autorów tej książki. W nowej strukturze takie zapytanie wymaga złączenia tabeli KsiazkiBibliotekarze z tabelą KsiazkiAutorzy po wspólnym atrybucie ISBN, ponieważ informacja o poleceniu książki i informacja o autorstwie znajdują się w różnych tabelach.

W oryginalnej strukturze to samo zapytanie byłoby prostym SELECT-em z filtrowaniem po ISBN, ale wynik zawierałby wszystkie kombinacje autorów i bibliotekarzy dla danej książki. Po dekompozycji każda kombinacja autora i bibliotekarza dla danej książki musi być jawnie złączona, co może być bardziej kosztowne obliczeniowo, ale jednocześnie bardziej przejrzyste i łatwiejsze do optymalizacji przez system zarządzania bazą danych. Dodatkowo, wynik złączenia jest wolny od fałszywych kombinacji.

W praktyce warto rozważyć utworzenie widoków SQL, które opakowują złączenia trzech tabel binarnych i prezentują dane w formie przypominającej oryginalną strukturę. Widoki takie mogą być użyteczne dla aplikacji, które wymagają dostępu do pełnych informacji o rekomendacjach, podczas gdy bezpośrednie zapytania do tabel binarnych są zarezerwowane dla precyzyjnych odczytów. Takie podejście łączy zalety normalizacji z wygodą programistyczną.

51/60Krok 11: Typowe błędy przy implementacji 5NF

Cztery typowe błędy

-- Błąd 1: Zakładanie JD tam, gdzie jej nie ma
-- Nie każda relacja trójskładnikowa ma JD!
-- Sprawdź JD testem COUNT przed dekompozycją

-- Błąd 2: Dekompozycja mimo braku JD
-- Jeśli JD nie jest spełniona, dekompozycja powoduje utratę danych!

-- Błąd 3: Mylenie kluczy w tabelach binarnych
-- W KsiazkiAutorzy: klucz = (ISBN, Autor) – obie kolumny
-- Bez klucza: duplikaty, redundancja

-- Błąd 4: Brak kluczy obcych między tabelami
-- FK: KsiazkiAutorzy.ISBN → Ksiazki.ISBN
-- Bez FK: dane sieroty
Cztery błędy: 1) zakładanie JD, 2) dekompozycja bez JD, 3) złe klucze, 4) brak FK. Pamiętaj: test COUNT to podstawa.
Cztery typowe błędy przy 5NF

W jedenastym kroku omawiamy najczęstsze błędy popełniane podczas implementacji piątej postaci normalnej, które mogą prowadzić do poważnych problemów z integralnością danych. Pierwszym i najpoważniejszym błędem jest zakładanie istnienia JD tam, gdzie w rzeczywistości nie jest ona spełniona. Programiści często mylnie zakładają, że każda relacja trójskładnikowa automatycznie zawiera JD, podczas gdy w praktyce większość takich relacji ma konkretne ograniczenia biznesowe, które uniemożliwiają spełnienie JD.

Drugim częstym błędem jest dekompozycja tabeli bez uprzedniego testu JD za pomocą złączenia projekcji. Jeśli JD nie jest spełniona, dekompozycja prowadzi do utraty informacji o rzeczywistych ograniczeniach biznesowych i generowania fałszywych wierszy podczas złączenia. Trzecim błędem jest nieprawidłowe zdefiniowanie kluczy głównych w tabelach binarnych, co może prowadzić do powstawania duplikatów i naruszenia integralności danych w nowych tabelach.

Czwartym błędem jest pominięcie kluczy obcych łączących nowe tabele binarne z istniejącymi tabelami słownikowymi. Brak kluczy obcych może prowadzić do pojawienia się danych sierot, czyli wierszy odnoszących się do nieistniejących encji w innych tabelach. Aby uniknąć tych błędów, zaleca się zawsze wykonywać test COUNT przed dekompozycją, starannie definiować klucze główne i obce oraz dokumentować reguły biznesowe uzasadniające dekompozycję.

52/60Krok 12: Podsumowanie implementacji 5NF

5NF w pigułce – 5 kroków

-- 5NF w pigułce:
-- 1. Sprawdź, czy tabela jest w 4NF (warunek konieczny)
-- 2. Zidentyfikuj potencjalne JD (podzbiory atrybutów)
-- 3. Sprawdź, czy JD jest spełniona (test COUNT)
-- 4. Jeśli JD spełniona: rozłóż na osobne tabele
-- 5. Jeśli JD nie spełniona: tabela jest w 5NF – nic nie rób

-- W praktyce: krok 3 prawie zawsze daje "NIE"
-- 5NF jest prawie zawsze automatycznie spełniona

-- Pamiętaj: 5NF to kraniec normalizacji. Dalej nie ma nic.
5 kroków do 5NF. Krok 3 (test COUNT) prawie zawsze daje 'JD nie spełniona'. Wtedy: nic nie rób, 5NF spełniona. Proste.
5 kroków do 5NF – podsumowanie implementacji

Podsumowując proces implementacji piątej postaci normalnej w systemie MariaDB, można wyróżnić pięć kluczowych kroków, które należy wykonać sekwencyjnie. Krok pierwszy polega na sprawdzeniu, czy tabela znajduje się w czwartej postaci normalnej, co jest warunkiem koniecznym do analizy 5NF. Krok drugi to identyfikacja potencjalnych zależności złączeniowych poprzez analizę podzbiorów atrybutów i sprawdzenie, czy każdy z nich jest nadkluczem.

Krok trzeci jest najważniejszy i polega na wykonaniu testu COUNT w celu sprawdzenia, czy JD jest faktycznie spełniona przez dane. Jeśli wyniki COUNT dla oryginalnej tabeli i złączenia projekcji są identyczne, JD jest spełniona. Krok czwarty to właściwa dekompozycja, czyli utworzenie osobnych tabel dla każdego podzbioru JD i przeniesienie odpowiednich danych. Krok piąty to weryfikacja poprawności dekompozycji poprzez ponowny test złączenia bezstratnego.

W praktyce krok trzeci prawie zawsze daje wynik negatywny, co oznacza, że JD nie jest spełniona i proces normalizacji kończy się bez modyfikacji schematu. Należy pamiętać, że 5NF to ostatnia postać normalna w modelu relacyjnym po jej osiągnięciu dalsza normalizacja nie jest możliwa ani potrzebna. Jeśli tabela znajduje się w 5NF, oznacza to, że jest w pełni znormalizowana zgodnie ze wszystkimi znanymi kryteriami teorii relacyjnych baz danych.

53/60Mapa całej normalizacji – od 1NF do 5NF

Sześć postaci normalnych

PostaćRokTwórcaEliminujeWarunek
1NF1970CoddNieatomowe wartościKażda komórka = jedna wartość
2NF1971CoddCzęściowe zależności1NF + pełna zależność od klucza
3NF1971CoddPrzechodnie zależności2NF + brak zależności przez atrybuty niekluczowe
BCNF1974Boyce, CoddNakładające się klucze (FD)3NF + każdy wyznacznik = nadklucz
4NF1977FaginWielowartościowe zależnościBCNF + brak produktu kartezjańskiego
5NF1979FaginZłączeniowe zależności4NF + wszystkie JD z kluczy
6 postaci normalnych, 3 twórców (Codd, Boyce, Fagin), 9 lat badań (1970-1979). Od atomowości po złączeniowe zależności. Kompletna teoria.
Mapa normalizacji – 6 postaci normalnych na osi czasu

Przegląd całego procesu normalizacji od pierwszej do piątej postaci normalnej ukazuje systematyczny rozwój teorii relacyjnych baz danych na przestrzeni dziewięciu lat. Pierwsza postać normalna, zdefiniowana przez Edgara Codda w 1970 roku, wprowadziła fundamentalne zasady atomowości wartości i eliminacji powtarzających się grup. Druga i trzecia postać normalna, również autorstwa Codda z 1971 roku, rozwinęły teorię zależności funkcyjnych, eliminując odpowiednio częściowe i przechodnie zależności między atrybutami.

BCNF, zaproponowana przez Boyce i Codda w 1974 roku, zaostrzyła wymagania trzeciej postaci normalnej, wymagając aby każdy wyznacznik zależności funkcyjnej był nadkluczem. Czwarta postać normalna, wprowadzona przez Ronalda Fagina w 1977 roku, rozszerzyła teorię na zależności wielowartościowe. Wreszcie piąta postać normalna, również autorstwa Fagina z 1979 roku, domknęła teorię normalizacji poprzez wprowadzenie zależności złączeniowych, które są najogólniejszym typem zależności w modelu relacyjnym.

Każda kolejna postać normalna jest bardziej restrykcyjna od poprzedniej, co oznacza, że relacja w 5NF jest automatycznie w 4NF, BCNF, 3NF, 2NF i 1NF. Ta hierarchiczna struktura postaci normalnych stanowi fundament teoretyczny projektowania relacyjnych baz danych i jest nauczana na wszystkich kierunkach informatycznych. Mimo że w praktyce rzadko stosuje się postaci wyższe niż 3NF, znajomość całej hierarchii jest niezbędna do pełnego zrozumienia możliwości i ograniczeń modelu relacyjnego.

54/60Ewolucja schematu biblioteki przez wszystkie normalizacje

Od 1 do 10 tabel

  • Dane surowe (bałagan) → 1 tabela Wypozyczenia z duplikacją
  • Po 1NF → 1 tabela z atomowością i kluczem głównym
  • Po 2NF → 3 tabele: Czytelnicy, Ksiazki, Wypozyczenia
  • Po 3NF → 4-5 tabel: + Miasta, opcjonalnie Gatunki
  • Po BCNF → 6 tabel: + Opiekunowie, Przypisania_BCNF
  • Po 4NF → 8 tabel: + Telefony, Emaile
  • Po 5NF → 9-10 tabel: + KsiazkiAutorzy, KsiazkiBibliotekarze, AutorzyBibliotekarze
Od 1 do 10 tabel – taka jest droga normalizacji. Każda nowa tabela przechowuje jeden fakt. Każda postać to jeden krok w stronę czystości.
Ewolucja schematu – od 1 do 10 tabel przez wszystkie postaci normalne

Śledząc ewolucję schematu bibliotecznego przez kolejne etapy normalizacji, możemy zaobserwować systematyczny wzrost liczby tabel przy jednoczesnym zmniejszeniu redundancji i eliminacji anomalii. Punktem wyjścia była jedna wielka tabela Wypozyczenia zawierająca siedemnaście kolumn, która łączyła dane czytelników, książek i wypożyczeń w jednej strukturze. Po pierwszej postaci normalnej tabela zachowała swoją strukturę, ale wszystkie wartości stały się atomowe, a klucz główny został zdefiniowany.

Druga postać normalna przyniosła radykalną zmianę: z jednej tabeli powstały trzy, rozdzielające dane czytelników, książek i wypożyczeń do osobnych struktur. Trzecia postać normalna dodała tabelę Miasta dla kodów pocztowych, a BCNF wprowadził tabele Opiekunowie i Przypisania_BCNF dla specyficznych zależności funkcyjnych. Czwarta postać normalna rozdzieliła dane kontaktowe czytelników na tabele Telefony i Emaile, zwiększając liczbę tabel do ośmiu.

Piąta postać normalna potencjalnie dodaje dwie lub trzy nowe tabele związane z systemem rekomendacji, w zależności od tego, czy JD jest spełniona i czy niektóre projekcje nie są już zaimplementowane w istniejącym schemacie. Ostatecznie, po pełnej normalizacji, schemat biblioteki może zawierać od dziesięciu do jedenastu wyspecjalizowanych tabel, z których każda przechowuje jeden rodzaj faktów i jest w pełni znormalizowana zgodnie ze wszystkimi wymaganiami teorii relacyjnych baz danych.

55/60Normalizacja w praktyce – co naprawdę stosujemy?

Co stosować w praktyce?

  • Większość systemów produkcyjnych: 3NF (czasem BCNF)
  • Systemy z wysokimi wymaganiami integralności: BCNF
  • Systemy z danymi kontaktowymi, tagami: 4NF
  • Systemy wymagające 5NF: PRAWIE NIGDY
  • Denormalizacja: czasem świadomie ŁAMIEMY normalizację dla wydajności

Przykład denormalizacji: dodanie LiczbaWypozyczen do Ksiazki – zamiast COUNT w zapytaniu.

W praktyce: 3NF to standard. BCNF i 4NF dla wymagających. 5NF – tylko w akademii. Denormalizacja – gdy wydajność wymaga.
Co naprawdę stosujemy? – piramida praktycznego użycia

W praktyce inżynierii oprogramowania rzadko stosuje się wszystkie postaci normalne w każdym projekcie, a wybór poziomu normalizacji zależy od konkretnych wymagań systemu. Trzecia postać normalna jest uznawana za standardowy poziom normalizacji dla większości systemów produkcyjnych, ponieważ zapewnia dobry balans między integralnością danych a wydajnością zapytań. BCNF jest stosowana w systemach o podwyższonych wymaganiach integralności, takich jak systemy bankowe czy medyczne, gdzie nawet subtelne anomalie mogą mieć poważne konsekwencje.

Czwarta postać normalna znajduje zastosowanie w systemach, które przechowują wiele niezależnych atrybutów dla jednej encji, takich jak numery telefonów, adresy e-mail czy tagi. W takich przypadkach 4NF eliminuje problem produktu kartezjańskiego między niezależnymi listami atrybutów. Piąta postać normalna, jak już wielokrotnie podkreślano, jest stosowana niezwykle rzadko i tylko w specyficznych sytuacjach, gdzie występują zależności złączeniowe.

Denormalizacja, czyli celowe odstąpienie od zasad normalizacji na rzecz wydajności, jest powszechnie stosowana w systemach raportowych i hurtowniach danych. W takich systemach dopuszczalne jest przechowywanie zduplikowanych danych lub preagregowanych wartości w celu przyspieszenia zapytań analitycznych. Kluczową zasadą jest jednak to, że denormalizacja powinna być świadomym wyborem opartym na pomiarach wydajności, a nie domyślnym podejściem do projektowania.

56/60Kiedy denormalizować? – praktyczne wskazówki

Denormalizacja = świadome złamanie zasad

Kiedy denormalizować:

  • Gdy JOIN-y są zbyt wolne (dodaj zduplikowane dane)
  • Gdy zapytania agregujące są zbyt częste (dodaj pre-agregowane kolumny)
  • Gdy system jest read-heavy (dużo odczytów, mało zapisów)
  • Gdy prostota kodu jest ważniejsza niż czystość danych

Kiedy NIE denormalizować:

  • Gdy dane często się zmieniają (ryzyko niespójności)
  • Gdy integralność danych jest krytyczna (banki, medycyna)
Denormalizacja to świadomy wybór – łamiesz zasady, bo wiesz, dlaczego. Nie ignoruj normalizacji – najpierw znormalizuj, potem ewentualnie zdenormalizuj.
Kiedy denormalizować – schemat decyzyjny

Decyzja o denormalizacji powinna być podejmowana świadomie na podstawie analizy wymagań wydajnościowych i charakterystyki operacji wykonywanych na bazie danych. Denormalizacja jest zalecana przede wszystkim w systemach, w których przeważają operacje odczytu nad operacjami zapisu, a wydajność zapytań jest krytyczna z punktu widzenia użytkownika. Typowymi przykładami są systemy raportowe, hurtownie danych i aplikacje analityczne, gdzie czas odpowiedzi na zapytanie jest ważniejszy niż optymalne wykorzystanie przestrzeni dyskowej.

Denormalizacja może polegać na dodaniu zduplikowanych kolumn do tabel w celu uniknięcia kosztownych złączeń, na przykład przechowywanie nazwy miasta bezpośrednio w tabeli Czytelnicy zamiast odwoływania się do tabeli Miasta za pomocą klucza obcego. Inną formą denormalizacji jest dodanie preagregowanych wartości, takich jak liczba wypożyczeń dla każdej książki, które są aktualizowane przy każdej operacji zapisu, ale znacznie przyspieszają zapytania agregujące. W obu przypadkach należy być świadomym ryzyka niespójności danych.

Denormalizacji nie zaleca się w systemach, w których dane często się zmieniają, ponieważ utrzymanie spójności zduplikowanych danych wymaga dodatkowej logiki biznesowej i zwiększa ryzyko błędów. W systemach transakcyjnych o wysokich wymaganiach integralności, takich jak systemy bankowe, medyczne czy rezerwacyjne, denormalizacja powinna być stosowana z dużą ostrożnością lub w ogóle unikana. W każdym przypadku decyzja o denormalizacji powinna być poprzedzona dokładnymi pomiarami wydajności i analizą kosztów utrzymania spójności danych.

57/60Normalizacja a wydajność – kompromisy

Porównanie wydajności

AspektPo normalizacji (3NF+)Po denormalizacji
INSERTSzybki (jeden wiersz)Wolniejszy (więcej wierszy/tabele)
UPDATESzybki (jeden wiersz)Wolny (wiele wierszy)
DELETESzybki (jeden wiersz)Ryzyko anomalii
SELECT (prosty)Wiele JOIN-ówJeden SELECT
SELECT (złożony)Bardzo elastycznyOgraniczony
MiejsceMałoWięcej (redundancja)

Normalizacja optymalizuje ZAPIS (INSERT/UPDATE/DELETE). Denormalizacja optymalizuje ODCZYT (SELECT).

Normalizacja = szybki zapis. Denormalizacja = szybki odczyt. Wybór zależy od tego, co robi Twój system.
Kompromisy normalizacji vs denormalizacji

Porównanie wydajności systemów znormalizowanych i zdenormalizowanych ujawnia fundamentalny kompromis między szybkością zapisu a szybkością odczytu danych. Systemy w pełni znormalizowane, zwłaszcza do 3NF i wyższych postaci, optymalizują operacje zapisu poprzez minimalizację redundancji i zapewnienie integralności danych. Każdy fakt jest przechowywany dokładnie w jednym miejscu, co oznacza, że operacje INSERT, UPDATE i DELETE są szybkie i bezpieczne, ale zapytania odczytu wymagają kosztownych złączeń między wieloma tabelami.

Systemy zdenormalizowane z kolei optymalizują operacje odczytu kosztem wolniejszych zapisów i większego zużycia przestrzeni dyskowej. Przechowywanie zduplikowanych danych eliminuje potrzebę złączeń, ale każda aktualizacja musi być propagowana do wszystkich kopii danych. W praktyce oznacza to, że wybór między normalizacją a denormalizacją zależy od charakterystyki systemu: systemy OLTP o dużej liczbie transakcji korzystają z normalizacji, podczas gdy systemy OLAP i hurtownie danych częściej stosują denormalizację.

Optymalnym podejściem jest często zastosowanie strategii hybrydowej, w której dane są przechowywane w postaci znormalizowanej dla operacji transakcyjnych, a dla celów raportowych i analitycznych tworzone są zdenormalizowane widoki lub osobne struktury danych. Takie podejście, znane jako architektura lambda lub architektura kappa, pozwala na czerpanie korzyści z obu światów przy jednoczesnym minimalizowaniu wad każdego z rozwiązań.

58/60Cały cykl prezentacji – podsumowanie

Siedem prezentacji – jeden cel

  • 'Historia baz danych' – jak doszliśmy do modelu relacyjnego
  • '1NF' – pierwszy krok normalizacji: atomowość, klucz główny
  • '2NF' – eliminacja częściowych zależności
  • '3NF' – eliminacja przechodnich zależności
  • 'BCNF' – silniejsza wersja 3NF: nakładające się klucze
  • '4NF' – eliminacja wielowartościowych zależności (MVD)
  • '5NF' – eliminacja złączeniowych zależności (JD) – TU JESTEŚMY

Każda prezentacja to jeden krok w podróży od bałaganu do czystej bazy danych.

7 prezentacji, od historii do 5NF. Każda postać normalna to odpowiedź na pytanie: 'jaki problem rozwiązuje ten krok?'
Podsumowanie cyklu – 7 prezentacji od historii do 5NF

Cały cykl prezentacji o normalizacji relacyjnych baz danych składał się z siedmiu części, prowadzących słuchacza od historii rozwoju baz danych przez wszystkie postaci normalne aż do 5NF. Prezentacja o historii baz danych wprowadziła kontekst i motywację do powstania modelu relacyjnego. Kolejne prezentacje szczegółowo omawiały każdą postać normalną, od 1NF zapewniającej atomowość, przez 2NF eliminującą częściowe zależności, 3NF usuwającą zależności przechodnie, BCNF zaostrzającą wymagania 3NF, 4NF rozwiązującą problem MVD, aż po 5NF domykającą teorię zależnościami złączeniowymi.

Każda prezentacja była oparta na tym samym przykładzie bibliotecznym, co pozwoliło na ciągłość narracji i pokazanie, jak ewoluuje schemat bazy danych w miarę stosowania kolejnych postaci normalnych. Punktem wyjścia była jedna wielka tabela z siedemnastoma kolumnami i licznymi anomaliami, a punktem docelowym zestaw dziesięciu wyspecjalizowanych tabel, z których każda jest w pełni znormalizowana i przechowuje jeden rodzaj faktów. Ta ewolucja ilustruje siłę i elegancję teorii normalizacji.

Mimo że w praktyce rzadko stosuje się wszystkie postaci normalne, znajomość całej hierarchii jest niezbędna do świadomego projektowania baz danych. Projektant, który rozumie teorię normalizacji, potrafi ocenić, kiedy proces normalizacji można zakończyć na 3NF, a kiedy konieczne jest zastosowanie wyższych postaci normalnych. Prezentacje te stanowią zatem kompendium wiedzy niezbędnej każdemu inżynierowi baz danych, niezależnie od stopnia zaawansowania projektowanych systemów.

59/60Ostateczna rada dla studenta

Normalizacja to narzędzie, nie dogmat

  • Pamiętaj: normalizacja to NARZĘDZIE, nie dogmat
  • Znasz reguły – możesz je świadomie łamać
  • W praktyce:
  • - 3NF: minimum dla każdej bazy produkcyjnej
  • - BCNF: gdy masz nakładające się klucze
  • - 4NF: gdy masz niezależne listy
  • - 5NF: gdy masz relacje trójskładnikowe z JD (prawie nigdy)
  • Projektuj od razu z myślą o normalizacji – przebudowa jest kosztowna
Normalizacja jak prawo jazdy: znasz przepisy, ale czasem jedziesz trochę szybciej. Ważne, by wiedzieć, co się robi i jakie są konsekwencje.
Ostateczna rada – normalizacja jako narzędzie

Ostateczna rada dla studentów kończących cykl nauki o normalizacji brzmi: traktuj normalizację jako narzędzie, a nie dogmat. Znajomość reguł normalizacji jest niezbędna, ale równie ważna jest umiejętność świadomego odstąpienia od tych reguł, gdy wymaga tego specyfika projektowanego systemu. W praktyce inżynierskiej najważniejsza jest umiejętność znalezienia złotego środka między czystością teoretyczną a wydajnością praktyczną, co wymaga doświadczenia i głębokiego zrozumienia kompromisów.

Zalecany poziom normalizacji dla większości systemów produkcyjnych to 3NF jako minimum, BCNF dla systemów o podwyższonych wymaganiach integralności, 4NF w przypadku niezależnych list atrybutów oraz 5NF tylko wtedy, gdy analiza reguł biznesowych wskazuje na istnienie zależności złączeniowych. Pamiętaj, że denormalizacja powinna być zawsze świadomym wyborem, a nie wynikiem ignorancji lub lenistwa projektowego. Projektuj od razu z myślą o normalizacji, ponieważ przebudowa istniejącego schematu jest zawsze bardziej kosztowna niż zaprojektowanie go poprawnie od początku.

Kończąc, zachęcam do dalszego zgłębiania tematyki baz danych poza standardowym kursem normalizacji. Warto zapoznać się z takimi zagadnieniami jak modelowanie wymiarowe w hurtowniach danych, bazy NoSQL i ich modele danych, a także nowoczesne techniki optymalizacji zapytań w systemach relacyjnych. Teoria normalizacji stanowi solidny fundament, ale prawdziwa biegłość w projektowaniu baz danych wymaga ciągłego uczenia się i praktyki w różnorodnych projektach.

60/60Dziękuję / Zakończenie cyklu

Gratulacje! Poznałeś całą teorię normalizacji relacyjnej baz danych!

Podsumowanie całego cyklu prezentacji:

  • 'Historia baz danych' – geneza modelu relacyjnego
  • '1NF' – pierwszy krok: atomowość (1970)
  • '2NF' – częściowe zależności (1971)
  • '3NF' – przechodnie zależności (1971)
  • 'BCNF' – nakładające się klucze (1974)
  • '4NF' – wielowartościowe zależności (1977)
  • '5NF' – złączeniowe zależności (1979)

Przesłanie: normalizacja to narzędzie, nie dogmat. Znaj normalizację jak reguły ruchu drogowego – ale czasem świadomie złam przepis dla wydajności.

Gratulacje! Poznałeś całą teorię normalizacji – od 1NF do 5NF. Jesteś gotów projektować czyste, wydajne bazy danych. Nie zapomnij: teoria to podstawa, ale praktyka weryfikuje.
Zakończenie cyklu – gratulacje i podsumowanie

Gratulujemy dotarcia do końca cyklu prezentacji o normalizacji relacyjnych baz danych. Od pierwszej publikacji Edgara Codda w 1970 roku, przez prace Ronalda Fagina w latach siedemdziesiątych, aż do współczesnych implementacji w systemach takich jak MariaDB, teoria normalizacji stanowi niezmienny fundament projektowania baz danych. Mimo upływu lat podstawowe zasady normalizacji pozostają aktualne i są nauczane na wszystkich kierunkach informatycznych na całym świecie.

Mamy nadzieję, że zdobyta wiedza pozwoli Państwu projektować czyste, wydajne i łatwe w utrzymaniu systemy bazodanowe. Pamiętajcie, że normalizacja to nie tylko zbiór reguł, ale przede wszystkim sposób myślenia o danych i ich wzajemnych powiązaniach. Umiejętność identyfikacji zależności między atrybutami, przewidywania potencjalnych anomalii i projektowania struktur minimalizujących redundancję jest nieoceniona w codziennej pracy inżyniera baz danych.

Życzymy powodzenia w dalszej nauce i rozwijaniu umiejętności w zakresie projektowania i administracji baz danych. Teoria normalizacji to dopiero początek drogi w świecie relacyjnych baz danych, ale stanowi niezbędny fundament dla bardziej zaawansowanych zagadnień, takich jak optymalizacja zapytań, modelowanie danych czy projektowanie systemów rozproszonych. Powodzenia na egzaminach i w przyszłej karierze zawodowej.