Postacie normalne

0

Mam takie pytanie. W skrócie 3 postać normalna zakłada że dane nie są od siebie zależne poza kluczem. Prowadzi to do konieczności złączeń.
Stąd pytanie czy warto zrezygnować z tej własności na rzecz szybszego szukania lub jego ułatwienia?

0
moskitek napisał(a)

Stąd pytanie czy warto zrezygnować z tej własności na rzecz szybszego szukania lub jego ułatwienia?

W sensie czy warto zrezygnować z trzeciej postaci normalnej ze względów wydajnościowych? W pewnych sytuacjach, gdy potrzebujemy szybkiego wyszukiwania danych, to tak. Na tym mniej więcej opierają się np. hurtownie danych.

0

czy warto zrezygnować z tej własności na rzecz ... ułatwienia

NIE. Nauczyć się sql.

0

to tak troche jak odp na inne pytanie (aktualnie piętro niżej):
http://4programmers.net/Forum/Bazy_danych/184297-mysql_optymalizacja_zapytan

ale też mówiąc o ułatwieniu - mając dość złożoną logikę biznesową czytanie długich zapytań, w których są "pokrętne" warunki (analizowanie/szukanie w nich błędów/pielęgnacja) jest mało przyjemna w porównaniu z sytuacją kiedy mam te dane w jako jeden atrybut.

1

Rób po bożemu, bo inaczej spotka Cię sroga kara, ucz się i rób jak bozia przykazuje. Wprawny programista SQL nie ma absolutnie żadnego kłopotu z ogarnięciem zapytań w których są INNER czy OUTER JOIN-y do 10 tabel, GROUP BY po 10 polach, a to wszystko jest złączone z kolejnymi 10 tabelami w podzapytaniu. Na dodatek serwerek SQL (nie cluster, nie cloud tylko serwerek) spokojnie to ciągnie, wystarczy wiedzieć co się robi. Pamiętaj, że SQL to język który znakomicie pokazuje poziom wiedzy programisty, ponieważ wszystko tam jest istotne łącznie z kolejnością tabel w złączeniu, kolejnością pól w indeksie, kolejnością pól w WHERE itd. Dobry programista jest w stanie tak zaprojektować tabele i zapytania, że chodzi to 1000 razy szybciej (DOSŁOWNIE!!!) niż gdyby to samo robił przeciętny klepacz stronek PHP, który nie wgłębiał się nigdy w arkana RDBMS.

1
moskitek napisał(a)

ale też mówiąc o ułatwieniu - mając dość złożoną logikę biznesową czytanie długich zapytań, w których są "pokrętne" warunki (analizowanie/szukanie w nich błędów/pielęgnacja) jest mało przyjemna w porównaniu z sytuacją kiedy mam te dane w jako jeden atrybut.

Odpowiednie formatowanie kodu, schemat bazy wydrukowany gdzieś przed oczami i czytanie kodu SQL nie jest problemem. Poza tym, to ma dobrze i wydajnie działać, a nie być przyjemne.

0

ok dzięki za odpowiedzi, ostatnio zacząłem mieć trochę wątpliwości i chciałem się upewnić.

0

Czasem stosuje się w pewnych wypadkach tzw płaski zapis, który jest "obok" danych zapisanych w 3 postaci normalnej. Dane takie są w specjalnej tabeli, bądź nawet jako string w pojedynczym polu. Rozwiązanie takie nie jest zbyt eleganckie, ale pomaga wydajnościowo w przypadku bardzo złożonej i rozpasanej bazie.

0

Odpowiedź brzmi "I tak i nie". Z jednej strony warto ułatwiać sobie życie pisząc proste zapytania. Z drugiej to co pisze AdamPL, czyli RDBMS poradzą sobie z 3PN jeżeli tylko programista wie co robi. Po środku pomiędzy tymi dwoma elementami mamy taki wynalazek jak widoki. Pozwalają one z jednej strony na uproszczenie zapytania ponieważ odpytujesz widok, a z drugiej przesłaniają rzeczywisty wygląd tabeli.

Jeżeli masz wybrać np. pracowników z pensją > 100 zamieszkałych w pcimiu, którzy robią na 3 rampie u pana Włodka, to wygodniej jest pytać widok "KOMPLETNE_DANE_PRACOWNIKA" niż rzeźbić join po 5 czy 6 tabelach. Recz w tym, że takie widoki muszą być przemyślane to znaczy, że trzeba wiedzieć do czego będą używane oraz warto postarać się napisać je najwydajniej jak się da założyć odpowiednie indeksy i zadbać o odpowiednią kolejność parametrów.

0

korzystając z ormów (np Hibernate) upraszczanie zapisu aby później za pomocą propertyResolverów sobie łatwo czytać dane jest bardzo kuszące.
O widokach nie pomyślałem :)

0

Pamiętaj, że żaden ORM nie jest tak wydajny jak raw sql, z tego też powodu tam gdzie potrzebna jest jak najwyższa wydajność rezygnuje się z ORM. Ostatnio tworzyłem w Django aplikację analityczną, rezygnacja z Django-wego ORM na rzecz żywych zapytań SQL przyniosła mi kilkudziesięciokrotny wzrost wydajności. Oczywiście zyskując na wydajności straciłem na wygodzie w utrzymaniu tego kodu, coś za coś.

0

@AdamPL, da się jedno z drugim pogodzić. ORM do tego co jest proste np. podgląd pojedynczych tabel czy zarządzanie jakimiś fragmentami danych. SQL do walki z danymi "na poważnie", raportowania, skomplikowanych procesów biznesowych itp. Szczególnie, że dobry ORM umożliwia zazwyczaj wykorzystanie SQLa.

0

@Koziołek - zrobiłem dokładnie tak jak to opisałeś. Modele wraz z relacjami, indeksami, a także proste zapytania mam zostawione w ORM, w raw SQL mam tylko złożone zapytania agregujące dane.

0

Jak będziesz miał 2 tabele z 14 mln rekordów to pojedyńczy join może zająć kilka godzin. W takim przypadku warto zdenormalizować dane.
Z drugiej strony gdy wprowadzasz redundancję to zwiększa się rozmiar bazy danych i użycie cache'a przestaje być efektywne.
Tak więc warto poeksperymentować jaki sposób będzie najlepszy.

0

@0x200x20, nie do końca. O tym co jest lepsze przekonałem się dziś na własnej skórze.

Problem:
Jest sobie tabela z transakcjami (przelewy, czeki, polecenia zapłaty itp.). Transakcji wchodzi ~15-18mln na dobę w czterech partiach przy czym zapis jest ciągły tzn. może nastąpić w dowolnym momencie doby, a aktualizacja rekordu w ściśle określonych warunkach i czasie. Dane w tabeli są w 1PN czyli jedna transakcja = 1 rekord. Wynikało to z możliwości wykorzystania mechanizmów bazy pozwalających na ładowanie danych bezpośrednio z pliku. Łatwe, proste i przyjemne. Do tego szybkie.
W tabeli trzymamy dane za kilka ostatnich dni, przy czym część klientów jest zainteresowana tylko danymi z bieżącej sesji, a część wszystkimi danymi z całego okresu kiedy trzymamy dane. Klucz główny jest złożony z kilku kolumn i jest kluczem naturalnym. Unikamy sztucznej sekwencji ponieważ i tak musimy zagwarantować unikalność danych. Robienie selecta przed insertem by sprawdzić czy aby nie ma już danego rekordu to głupi pomysł.

Jak się okazało przy testach wydajnościowych przeszukiwanie takiej tabeli (nie za dużej w sumie) wyszukanie pojedynczego rekordu po części klucza głównego trwa kilka minut. Dlaczego? Klucz główny to 400 bajtów. Indeks będzie miał 400*20 000 000~ 8GB/dzień. Jak szukamy po części klucza to dupa blada trzeba ten indeks przeskanować. Jeżeli w tym czasie idą jeszcze aktualizacje i wstawienia to kompletna klapa.

Rozwiązaniem okazało się podzielenie klucza głównego i przeniesienie jego części do osobnej tabeli. Dodaliśmy tam jako klucz główny sztuczną sekwencję, a unikalność danych gwarantujemy za pomocą dodatkowego, unikalnego indeksu na wszystkich kolumnach. Zapytanie wykonuje się kilkanaście sekund.

Dlaczego tak się stało? Po pierwsze wydzieliliśmy powtarzające się dane. Ta dodatkowa tabelka w skrajnym przypadku nie może być większa niż ~100000 rekordów. W praktyce nie przekracza 10000. Po drugie wyszukujemy dane w mniejszej tabelce. Maksymalna wielkość indeksu to ~40MB. Następnie dopiero z większej tabeli dobieramy dane pasujące do reszty oryginalnego klucza głównego. I tu znowu indeks będzie maleńki ~0,5GB. W dodatku optymalizator wybrał szybszy sposób przeszukiwania ponieważ w głównej tabeli szukamy już danych których jest niewiele w porównaniu z całym zbiorem (maks ~3000). Do tego doszły jeszcze dodatkowe indeksy dla przeszukiwania pełnotekstowego i bangla.

0
AdamPL napisał(a)

@Koziołek - zrobiłem dokładnie tak jak to opisałeś. Modele wraz z relacjami, indeksami, a także proste zapytania mam zostawione w ORM, w raw SQL mam tylko złożone zapytania agregujące dane.

Wszystko pięknie, tylko w takim razie po co używasz orm-a, skoro:

  • i tak używasz sql
  • orm używasz tylko dla PROSTYCH zapytań, czyli zakładając że orm ma uwolnić cię od klepania ręcznego zapytań, niewiele zyskałeś na tym

Poza tym, czemu by nie przenieść jak najwięcej logiki na bazę danych (procedury/funkcje), zamiast klepać zapytania w kodzie programu? W końcu łatwiej zarządzać bazą danych niż binarkami u 50 klientów z niej korzystających (przykładowo). Tylko, że: znów używanie orm-a tylko do wywoływania procedur to tez lekki bezsens.

1

@othello, proste może oznaczać np. wyszukiwanie obiektów biznesowych. Jak trzeba przejść przez 3-4 tabelki to ORM zrobi to lepiej. Sqla można oszczędzić na znacznie bardziej skomplikowane zadania np. raportowanie. Względnie tam gdzie chcesz wykorzystać np. hinty.

1

@othello - w aplikacji o której pisałem jest masa niewielkich zapytań o pojedyncze obiekty z wielu tabel, tam ORM sprawdza się znakomicie i rzeczywiście odciąża programistę oraz pozwala mu operować na całych obiektach, a nie pojedynczych polach z pojedynczych rekordów. Żeby wytłumaczyć Ci zalety ORM musiałbym najpierw zrobić wykład na temat zalet programowania obiektowego, a to nie jest czas i miejsce na takie wywody.

1 użytkowników online, w tym zalogowanych: 0, gości: 1