Czym jest normalizacja bazy danych (i kiedy łamać jej zasady)?
Normalizacja baz danych uchodzi za temat akademicki, pełen reguł o uczenie brzmiących nazwach – pierwsza postać normalna, druga postać normalna i tak dalej – ale idea, która za nią stoi, jest zaskakująco praktyczna: zorganizujcie dane tak, by ten sam fakt nigdy nie musiał być zapisany w dwóch miejscach, bo w chwili, gdy tak się stanie, te dwa miejsca prędzej czy później zaczną sobie przeczyć.
Główny problem, który rozwiązuje normalizacja
Wyobraźcie sobie tabelę, która przechowuje zamówienie wraz z pełnym imieniem i nazwiskiem klienta oraz jego adresem e-mail bezpośrednio w każdym wierszu. Jeśli klient zmieni adres e-mail, trzeba zaktualizować każdy wiersz zamówienia, w którym się pojawia – a jeśli pominiecie choć jeden, dane po cichu staną się niespójne i w tej samej bazie zamieszkają dwie różne „prawdy”. Normalizacja rozwiązuje ten problem, przechowując dane klienta w jednym miejscu (w tabeli klientów) i odwołując się do nich przez identyfikator wszędzie tam, gdzie są potrzebne.
Postacie normalne bez żargonu
- Pierwsza postać normalna: każda kolumna przechowuje jedną wartość, a nie listę wciśniętą w jedno pole. Kolumna „phone_numbers” z trzema numerami rozdzielonymi przecinkami łamie tę zasadę.
- Druga postać normalna: każda kolumna niebędąca kluczem zależy od całego klucza głównego, a nie tylko od jego części – ma to znaczenie głównie w tabelach z kluczami złożonymi.
- Trzecia postać normalna: kolumny niebędące kluczem zależą wyłącznie od klucza, a nie od siebie nawzajem. Jeśli miasto klienta da się wyprowadzić z kodu pocztowego, przechowywanie obu wartości bezpośrednio prosi się o to, by w końcu przestały się zgadzać.
W praktyce większość dobrze zaprojektowanych systemów celuje w trzecią postać normalną i na niej poprzestaje. Dalsze postacie istnieją głównie w podręcznikach, a nie w prawdziwych schematach produkcyjnych.
Co daje normalizacja
Spójne dane bez powielonych faktów, które mogłyby się przypadkiem rozjechać, mniejsze zużycie miejsca, bo te same wartości nie powtarzają się w wielu wierszach, oraz łatwiejsze aktualizacje – zmieniacie fakt w jednym miejscu, a każde odwołanie do niego automatycznie uwzględnia zmianę.
Kiedy ścisła normalizacja zaczyna kosztować
Ceną jest złożoność zapytań. Silnie znormalizowane dane rozproszone po wielu małych tabelach często oznaczają złączanie kilku tabel tylko po to, by odpowiedzieć na proste pytanie, a każde złączenie ma realny koszt wydajnościowy. W systemach nastawionych na odczyt – panelach raportowych, analityce, wszędzie tam, gdzie zapytań jest dużo więcej niż zapisów – ten koszt może mieć naprawdę duże znaczenie.
I tu pojawia się celowa denormalizacja: świadome powielanie części danych, by uniknąć kosztownych złączeń, w zamian za szybsze odczyty. To uprawniona, powszechna strategia – a nie wada projektu – o ile jest świadomym kompromisem, a nie przypadkiem. Wiele prawdziwych systemów normalizuje kluczowe dane transakcyjne, a obok utrzymuje zdenormalizowaną, zoptymalizowaną pod odczyt kopię przeznaczoną specjalnie do raportów lub dashboardów.
Praktyczny wniosek
Normalizujcie domyślnie, zwłaszcza dane, w których spójność naprawdę ma znaczenie – pieniądze, stany magazynowe, wszystko, co nigdy nie może po cichu przeczyć samo sobie. Denormalizujcie świadomie i tylko tam, gdzie faktycznie zmierzyliście realny problem z wydajnością spowodowany złączeniami. Zgadywanie w tej kwestii w którąkolwiek stronę, bez wcześniejszych pomiarów, prowadzi do schematów, które albo nie dają się wydajnie odpytywać, albo są pełne danych subtelnie niezsynchronizowanych. Znalezienie właściwej równowagi dla rzeczywistych wzorców odczytu i zapisu konkretnego produktu to sedno naszej pracy nad oprogramowaniem na zamówienie i infrastrukturą.