Svođenje modela na prvu normalnu formu
Krenućemo od jednostavne strukture; imamo spisak članova foruma koji imaju nekakvo znanje o raznim materijama. Neki članovi znaju o muzici, neki o hardware-u dok se neki bolje snalaze sa linux-om; naravno, postoje i oni koji vrlo dobro poznaju i hardware i muziku. Primer jednostavne tabele bi izgledao ovako:
ID: 1
KORISNIK: pera peric
ZIVI: Srbija
ZNANJE: AudioID: 2
KORISNIK: mika mikic
ZIVI: Srbija
ZNANJE: VideoID: 3
KORISNIK: zikica zikic
ZIVI: Srbija
ZNANJE: Audio, Video, Hardware, WindowsID: 4
KORISNIK: mali perica
ZIVI: Srbija
ZNANJE: Audio, Video, Baze, Hardware, Windows, Linux, ProgramiranjeID: 5
KORISNIK: mali zikica
ZIVI: BIH
ZNANJE: Programiranje, Hardware
Ovo je tipičan primer clipperovski modelirane tabele i to je ono što se često viđa na production sistemima danas. Onda se klijenti pitaju zašto im je aplikacija spora i zašto upiti traju satima; a posle redizajna pitaju kako je moguće da proces koji je trajao po ceo vikend sada traje ispod 30 sekundi. No, da nastavimo …
Ako želimo da saznamo koji korisnik zna „video“ moramo proći kroz sve korsnike, proveriti sadržaj polja „znanje“ i pregledati prilicno nepregledno polje „znanje“ te otkriti da li dotični korisnik zna „video“ ili ne. Mane ovakve organizacije su očigledne (brzina, preglednost…) te je ovo vrlo nepraktičan nacin za čuvanje informacija.
Klasificiranje podataka u zasebne tabele će „prisrediti“ podatke i omogućiti lakšu pretragu. Razdvajanje repetitivnih podataka u zasebne tabele našu strukturu dovodi u prvu normalnu formu.
Iz našeg primera (gde je sve bilo nagurano u istu tabelu), dobijamo 2 odvojene tabele:
TABELA: KORISNIK
KORISNIK_ID: 1
KORISNIK_IME: pera peric
KORISNIK_ZIVI: SrbijaKORISNIK_ID: 2
KORISNIK_IME: mika mikic
KORISNIK_ZIVI: SrbijaKORISNIK_ID: 3
KORISNIK_IME: zikica zikic
KORISNIK_ZIVI: SrbijaKORISNIK_ID: 4
KORISNIK_IME: mali perica
KORISNIK_ZIVI: SrbijaKORISNIK_ID: 5
KORISNIK_IME: mali zikica
KORISNIK_ZIVI: BIH
TABELA: ZNANJE
ZNANJE_ID: 1
KORISNIK_ID: 1
ZNANJE_IME: AudioZNANJE_ID: 2
KORISNIK_ID: 2
ZNANJE_IME: VIDEOZNANJE_ID: 3
KORISNIK_ID: 3
ZNANJE_IME: AudioZNANJE_ID: 4
KORISNIK_ID: 3
ZNANJE_IME: VideoZNANJE_ID: 5
KORISNIK_ID: 3
ZNANJE_IME: HardwareZNANJE_ID: 6
KORISNIK_ID: 3
ZNANJE_IME: WindowsZNANJE_ID: 7
KORISNIK_ID: 4
ZNANJE_IME: AudioZNANJE_ID: 8
KORISNIK_ID: 4
ZNANJE_IME: VideoZNANJE_ID: 9
KORISNIK_ID: 4
ZNANJE_IME: BazeZNANJE_ID: 10
KORISNIK_ID: 4
ZNANJE_IME: HardwareZNANJE_ID: 11
KORISNIK_ID: 4
ZNANJE_IME: WindowsZNANJE_ID: 12
KORISNIK_ID: 4
ZNANJE_IME: LinuxZNANJE_ID: 13
KORISNIK_ID: 4
ZNANJE_IME: ProgramiranjeZNANJE_ID: 14
KORISNIK_ID: 5
ZNANJE_IME: HardwareZNANJE_ID: 15
KORISNIK_ID: 5
ZNANJE_IME: Programiranje
Sada je na pitanje „koji korisnik zna video?“ mnogo lakše odgovoriti.
Zar se relacija ne prevodi u 1NF bez razdvajanja u 2 relacije? Hoću reći da je ovde dovoljno da se za višeznačnu zavisnost {ID} →→ {ZNANJE} za svaki element tupea napravi novi red u početnoj tabeli. Npr. za ID 5 bi imali imali 2 reda:
ID: 5
KORISNIK: mali zikica
ZIVI: BIH
ZNANJE: Programiranje
ID: 5
KORISNIK: mali zikica
ZIVI: BIH
ZNANJE: Hardware
Jeste da je grozota, ali je u 1NF sa složenim ključem {ID, ZNANJE}, a nije u 2NF jer atributi {KORISNIK} i {ZIVI} ne zavise od celog ključa već samo od {ID}
Video sam da neki profesori na domacim fakultetima tvrde da je to tacno (tj da je jedan entitet u ovom slucaju dovoljan za 1NF) ali se ja ne slazem (a bogami ni malo ozbiljnija literatura). U ovom slucaju za prvu normalnu formu moramo da imamo 2 entiteta. Primer sa jednim entitetom nije prva normalna forma, u nekoj literaturi se naziva „nulta normalna forma“, u nekoj „tranzitivno stanje pred prvu normalnu formu“ dok se u vecini literature „ne zove“ :).
Prva normalna forma dobija u zadnje vreme malo vise na znacaju sa noSQL bazama i nasledjivanjem ali tu opet vaze neka druga pravila tako da je „(de)normalizacija“ u 90% slucajeva kod noSQL baza pogresan termin. Model baze mora da se redefinise da bi se prilagodio noSQL limitima i da bi se iskoristile prednosti noSQL-a ali taj proces trenutno nema „ime“ i nije „naucno obradjen“. Verovatno ce za par godina neko napraviti phD rad na tu temu, imenovati proceduru, podeliti je na stepene pa cemo imato „nosqlizaciju prvog, drugog … ntog stepena“ ali otom potom, ovo je ipak blog prilicno vezan za MySQL te nas zanima klasicna normalizacija
Malo sam proguglao netom i izgleda da postoji neslaganje oko uslova koje 1nf treba da zadovolji, pa bih rekao da postoji škola koja promoviše blaže i škola strožijih uslova (fin primer blaže škole: http://www.phlonx.com/resources/nf3/).
U svakom slučaju se prevođenjem u 2nf rezultata prevođenja u 1nf dolazi do istog razultata, bez obzira kojom smo školom došli do 1nf. Pretpostavljam da je profesorima (domaćim a i stranim) lakše da koriste blaže uslove i da postupnije prevode u 2nf nego da budu direktni primenom strožijih uslova.
Setih se jedne zgodne izreke za normalizaciju:
The data depends on the key [1NF], the whole key [2NF] and nothing but the key [3NF] so help me Codd.
Što se noSQL-a tiče, lepo smo proslavili noSQL summer u Beogradu sa 2 predavanja: http://scalability.rs/blog
:) da tu je nezgoda sto ako gledas samo „key/whole key/nothing but the key“ onda jeste … ono gde se ne slazu je definicija uslova, ne interpretacija :D .. generalno ne preterano bitno .. za skolu – naucis kako profa kaze i briga te sta je u stvari, za realni zivot nije preterano bitno kako se zove bitno da radi ono sto ti treba :D