Normalizować czy nie ? MySQL

0

Tworzę aplikację desktopową, która będzie korzystać z bazy danych służy do zbierania informacji o ubezpieczonych.Przykładowo mamy ubezpieczenie wyjazdu i w aplikacji zaznaczamy cele podróży: turystyka, praca etc. Oczywistym wydaje się być to by utworzyć w bazie osobną tabelę np. typ_podrozy i do tabeli odnośnie ubezpieczenia_wyjazdowe stworzyć związek 1:N. Pytanie jednak co jeżeli danych będzie dużo i trzeba będzie tworzyć powiązania w zapytaniu ? Wiem, że typów podróży będzie niewiele - 4. Stąd moje takie pytanie czy w tej sytuacji za wszelką cenę muszę to normalizować. Czy nie lepszym rozwiązaniem pod względem wydajności będzie takie -w tabeli zawierającej ubezpieczenia przechowywać typy podróży w osobnej kolumnie w taki sposób:

 
praca,turystyka
praca
turystyka
praca, turystyka

lub osobne kolumny dla każdego typu podróży i typ logiczny - 0 lub 1.

Z poziomu programu tylko parsować te dane. Czyli pobierać całą wartość kolumny i jeżeli jest praca to zaznaczyć, że celem podróży klienta jest praca itp.

0

ta a jak NAGLE dojdzie nowy typ to będziesz pół aplikacji przerabiał... Zrób raz a porządnie i miej z głowy

1

Ja bym się nie przejmował. Gorzej jakbyś chciał łączyć dwie tabele które mają po 1 000 000 rekordów. W takim przypadku nawet nie odczujesz różnicy w wydajności.

Jak się tak boisz o wydajność to zainstaluj sobie jakieś sensowne oprogramowanie które wskaże Ci plan zapytania oraz wypisze statystyki ile czasu zajęło wykonanie zapytania. Wtedy zobaczysz co i jak.

Oczywiście dochodzą te sprawy o których kolega wcześniej powiedział. Takie coś ewidentnie trzeba wsadzić do oddzielnej tabeli. Jeśli to nie będzie nigdy zmieniane, to nie musisz pokazywać tego użytkownikowi do edycji i już.

2

Najwydajniejsze i najprostsze będzie trzymanie tego w jednym polu jako lista / tablica / zbiór, o ile Twój RDBMS ma taki typ danych. Niektóre systemy potrafią nawet indeksować takie pola, więc wyszukiwanie po nich jest b. szybkie.

Osobne kolumny to zły pomysł, bo jak dojdzie nowy typ, będziesz musiał robić ALTER TABLE, co może być kosztowne, no i będziesz musiał to później w każdym zapytaniu uwzględnić (potencjalnie dużo zmian kodu).

Takie coś ewidentnie trzeba wsadzić do oddzielnej tabeli.

Można, ale niekoniecznie "ewidentnie trzeba".
Jak się tak w ciemno robi, to później ma się zapytania, które mają 20 joinów i wyciągnięcie jednego rowka trwa pół minuty (widziałem taką bazę, gdzie przegięli z normalizacją). MySQL jest szczególnie kiepski w złączeniach i jak masz więcej niż 3, to optymalizator dostaje kręćka i robi głupoty.

Jak jest wiele do wielu (z treści posta do końca nie wynika, ale podajesz przykład że dwa typy podróży są przyporządkowane do jednego ubezpieczenia, czyli N:N, a nie N:1), to musisz mieć pośrednią tabelę złączeniową, której rozmiar będzie porównywalny do większej tabelki z tych złączanych. Czyli dochodzą Ci dwa joiny, z czego jeden nietrywialny (duża tabelka z dużą), a jeden można pewnie pominąć. Zakładając, że nie ma tam innych złączeń, spowolnienie w dostępie do danych co najmniej dwukrotne (uderzenie w dwa indeksy, zamiast jednego).

1

Jeśli w bazie potrzebujesz trzymać tylko wartości, a nie opisy (bo te masz tylko po stronie aplikacji), a liczba typów podróży jest stała, to wystarczy mieć enum w aplikacji, zapisywany do kolumny typu całkowitoliczbowego. Łatwo, prosto i bez joinów.

Tabele słownikowe są potrzebne wyłącznie wówczas, gdy chcesz, aby użytkownik aplikacji miał możliwość dodawania nowych typów.

0
Krolik napisał(a):

Najwydajniejsze i najprostsze będzie trzymanie tego w jednym polu jako lista / tablica / zbiór, o ile Twój RDBMS ma taki typ danych.

Z ciekawości - które to rdbms pozwalają na tworzenie kolumn tabeli, które są typu tablicowego? Oracle nie, Mysql nie, MS SQL raczej też nie.

0

@Świetny Samiec. Na Oracle, MS SQL, a tym bardziej MySQL świat (baz) się nie kończy. Np. postgreSQL pozwala na tworzenie typu tablicowego. I z tego co pamiętam ADABAS również to potrafił :)

0

Mhmm, powiedzmy że to wiodące i kosztujące grubą kasę nie pozwalają. Dwa główne to MS SQL i Oracle, tam tego nie ma (chyba że jest?) bo temat dość ciekawy.

0

Postgres jest jedną z wiodących (top 10) i potrafi robić tablice. Enterprise DB to przecież komercyjna baza z pełnym wsparciem. Nie rozumiem, czemu ktoś miałby ją odrzucać bo jest open-source. Dla firm powinna być to raczej zaleta niż wada.

Za to z wiodących baz prawie relacyjnych (tj. tabelkowych, ale nie-do-końca SQL), Cassandra ma pola typu set, list, map, tuple, json oraz strukturalne (user defined types). No i można je dowolnie zagnieżdżać.

Owszem, Postgres i Cassandra nie są tak popularne jak bazy z wielkiej trójki Oracle, MSSQL, DB/2 ale popularność tej trójki wynika raczej z ich długiego istnienia w epoce sprzed open-source i tradycji, a nie z ich merytorycznej "lepszości". Jeszcze 10 lat temu nikomu w banku nie śniło się przechodzić z Oracle na Postgresa, a obecnie słyszałem już o dwóch takich przypadkach. O przypadkach przechodzenia z Oracle na Cassandrę nie będę pisał, bo siłą rzeczy byłbym nieobiektywny ;)

0

No nie wiem, czy powinieneś stawiać Postgresa w jednym rzędzie z Oracle. Kwestia klastrowania, zarządzania i administracji bazą, wydajności przy wielkiej ilości danych itd. O administracji serwerami baz Oracle można napisać encyklopedię, tak samo o optymalizacji bazy, różnych metodach klastrowania serwerów, dbfs, ocfs itd. Gdzie przy tym jest postgres? Toż to malutka bazka tylko i w miarę prosta.

Czasem można zmigrować z Oracle an Postgresa, ale powiedz mi jak zmigrujesz klaster serwerów Oracla, współdzielący dane przez ocfs2 chociażby, ze skonfigurowanymi listenerami, broadcastowymi adresami sieciowymi itd. Jeśli ktoś zmigrował sobie Oracle do Postgresa, to znaczy że takiej bazy jak Oracle nie potrzebował zasadniczo nigdy

0

@Krolik no ale nie wymieniaj mi kto to przeszedł już na Posgresa. Wszystko zależy czego potrzebujesz. Przestaw mi w Posgresie alternatywę dla klastra wydajnościowo-niezawodnościowego złożonego z 5 serwerów bazodanowych Oracle tak np. Przedstaw alternatywę dla chociażby data pump, zarządzania tablespace'ami, archive log itd. Przecież w Posgresie tego wszystkiego nie da się osiągnąć. Porównujesz do siebie 2 zupełnie inne rzeczy.

Nie twierdzę, że Posgres jest zły, ale wszystko to kwestia skali i potrzeb. Pewnie że jak ktoś ma jedną bazę na pojedynczym serwerze Oracle, to może to sobie zmigrować to PosgreSQL i będzie mieć to samo, ale zajmie mniej miejsca, zje mniej zasobów i będzie prostsze w zarządzaniu (bo zarządzanie de facto ogranicza się do stworzenia użytkowników i nadania im uprawnień). Ale przecież nie o tym mowa.

0

przy rozwiązaniu "w tabeli zawierającej ubezpieczenia przechowywać typy podróży w osobnej kolumnie w taki sposób" problem może pojawić się wtedy gdy okaże się. że są jeszcze jakieś inne typu, których nie uwzględniłeś w trakcie pisania aplikacji (a tak często bywa w życiu, np. firma postanowiła ubezpieczać skoczków spadochronowych). Dodawanie nowych kolumn w przetestowanym i oddanym do użytkowania programie to koszmar programisty (nowy kod, nowe testy). Jeżeli program jest typowo desktopowy to rozumiem, ze w bazie nie będzie raczej milinów rekordów więc wydajność nie jest problemem sama w sobie i osobiście poszedłbym raczej w relacje z użyciem dodatkowej tabeli jako słownika.

0
Krolik napisał(a):

Można, ale niekoniecznie "ewidentnie trzeba".
Jak się tak w ciemno robi, to później ma się zapytania, które mają 20 joinów i wyciągnięcie jednego rowka trwa pół minuty (widziałem taką bazę, gdzie przegięli z normalizacją). MySQL jest szczególnie kiepski w złączeniach i jak masz więcej niż 3, to optymalizator dostaje kręćka i robi głupoty.
Faktycznie, przesadziłem nieco z mocą mojego twierdzenia. Czasem warto takie coś wyciągnąć do oddzielnej tabeli. Chodzi o to, że czasem taka tabela ma nie tylko pola:

  • ID
  • OPIS
    Ja u siebie w systemie mam kilka takich rzeczy które musiałem wydzielić do oddzielnej tabeli, bo okazało się, że user chciałby zmieniać pewne rzeczy. Więc aby można było to parametryzować, to dorzuciłem kilka pól do tabeli i w zależności jaki to jest typ zmienia mi się działanie programu. Wtedy faktycznie mam kolejnego joina, ale możliwości systemu każdy może dostosować do siebie.

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