[Struktura] Wiele tabel czy jedna zbiorcza?

0

Tworze sobie oprogramowanie przechowujace dane klientow, faktur, pracownikow, itp. Oprogramowanie wspiera wielojezycznosc.

Opracowalem sobie tabele

create table Content
(
  Language varchar(10) not null, 
  ContentType varchar(255) not null,
  ForeignID integer,
  CompanyID integer foreign key (Companies.ID),
  Content text,
  primary key (Language, ContentType, ForeignID, CompanyID)
)

gdzie:

  • Language - wiadomo
  • ContentType - rodzaj zawartosci, np. 'CancelLabel' - pasujace do wszystkich przyciskow typu Anuluj
  • ForeignID - klucz obcy w kilku tabelach, wyjasnienie ponizej
  • CompanyID - id firmy
  • Content - tresc danej wartosci

Przykladowo wpisujac domyslne wartosci jednostek produktow dam

insert into Content (Language, ContentType, ForeignID, CompanyID, Content) values('pl', 'UnitType', 1, 15, 'gram')

czyli dla firmy o ID 15 jedna z uzywanych jednostek w jezyku polskim jest jednoska o ID = 1 i nazwie = 'gram'. Dla ulatwienia tworze sobie w bazie widok Units, gdzie ustawiam na sztywno kolumne ContentType.

ForeignID moze byc nullem dla wartosci globalnych (tresc stopki na stronie, czy tresc informacji o programie, wtedy i CompanyID jest nullem). Moze byc kluczem obcym, jezeli bierzemy pod uwage np. stanowisko pracownika o okreslonym ID - wtedy widok domyslnie laczy tresc stanowiska w konkretnym jezyku z danymi z tabeli Customers.

Takich ContentType bedzie wiele w tej tabeli: jednostki, stawki VAT, powody zwrotu towaru, klasa pochodzenia towaru, itp. Slowem tabela rozrosnie sie dosc szybko.

Pytanie brzmi: czy takie rozwiazanie ma jakies wady i czy lepiej podzielic ta tabele na kilka- byc moze nascie tabel do okreslonych celow, gdzie kolumny beda bardzo podobne.
Zmysl programisty wzdryga sie na sama mysl tworzenia wielu tabel o praktycznie identycznych wlasciwosciach, wiec to rozwiazanie jest dla mnie lepsze. Tym bardziej, ze ja ulatwiam sobie zycie tworzac procedury wstawiania/zmiany odpowiednich wartosci i widoki do ich odczytywania - teoretycznie wiec tej bazy nie dotykam. Ktos, kto chcialby odczytac strukture bazy tez moze rzucic okiem na bazy i procedury i raczej sie domysli po co ta jedna.

Czy z punktu bazy to obojetne (kolos czy wiele kopii to konkretnych celow) czy ma wplyw na wydajnosc? Bo co do drugiego to nie wydaje mi sie, ale chetnie sie upewnie :)

Licze na konkretne odpowiedzi, w razie czego sluze dalszymi wyjasnieniami :)

0
  1. a co w takim przypadku
INSERT INTO Content (LANGUAGE, ContentType, ForeignID, CompanyID, Content) VALUES('pl', 'UnitType', 1, 15, 'gram');
INSERT INTO Content (LANGUAGE, ContentType, ForeignID, CompanyID, Content) VALUES('pl', 'UnitType', 1, 15, 'kilogram');

(nie wiem co wstawić w ForeignID)
czyli masz kilka jednostek masy i nie możesz ich tak wstawić bo nie da się ich rozróżnić - musiał byś mieć ContentType dla nich. Dodatkowo np. przy masach wiesz, że 1kilogram to 1000gramów i możesz sobie to przeliczyć ALE musisz wiedzieć, że konkretny wpis w Twojej tabeli to kilogram a inny konkretny to gram.
Podobnie ze stawkamia VAT - wiesz, że 7% to 0.07 wartości, 22% to 0.22 wartości a ZW to 0% wartości (do wyliczania podatku, np na f-rze). Teraz musisz jakoś powiązać konkretny wpis z tym, że to jest 0.07 wartości a inny konkretny 0.22 wartości.
Inaczej mówiąc jeśli nie chcesz się wkopać to musisz to przemyśleć. Ja mam tak, że wszystkie konkretne grupy są w osobnych tabelach, i tak mamy tabeleę stawki_vat (id, lang, stawka_wydruk, stawka_wartosc) (stawka wydruk to to co się ma drukować, czyli np. 22%, 7% ZW, a stawka_wartosc to wartość do obliczeń, np. 0.07, 0.22, 0)
mamy tabelę jednostki (id, lang, typ, jednostka_wydruk, przelicznik) typ to typ, np. masa, objętość.

O ile takie rzeczy jak stawka vat, jednostka, nazwy dokumentów itp nie zależą od kontrahenta a jedynie od języka o tyle np. nazwy własne towarów (np. towar nazywa się szynka jakaśtam ale na f-rze dla kauflanda musi się nazywać szynka-inna jakaśtam) oprócz języka zależą już od konkretnego kontrahenta. Ale taka zależność jest praktycznie tylko dla nazw towarów. i same nazwy są w osobnej tabeli, gdzie jest id_towaru, lang, id_kontr, nazwa, snazwa.

0

Co do inserta to ForeignID jest zawarte w kluczu glownym, wiec drugi zestaw narusza unikalnosc klucza. Jednostek przeliczac nie bede - klient nie chce takiej funkcjonalnosci, wiec nazwa jednostki i wiekszosci innych to po prostu tekst. Maja sluzyc po prostu jako dodatkowy 'znaczek' po np. liczbie produktow.

Stawki VAT juz przenioslem do innej tabeli (bo bede uzywal do wyliczania), wiec tego nie bierzmy juz pod uwage.

Nazwy towarow pozostaja w formie wpisanej przez uzytkownika (rowniez zgodnie z wymaganiami klienta).

Generalnie to co tutaj przedstawilem jest zgodne w pelni z wymaganiami przedstawionymi przez klienta. Klient wymagan raczej nie zmieni (wiem, ryzykowne zalozenie), bo moja firma dostaje nie za duzo za ten projekt, wiec raczej niczego takiego nie ustala. W razie koniecznosci zmian (czyli rozdzielenia) moge po prostu utworzyc tabele blizniacza aktualnego widoku i przeniesc wartosci - tutaj bym nie upatrywal problemu.

Bardziej mnie interesuje czy takie rozwiazanie nie ma jakichs pulapek pojawiajacych sie juz w trakcie dzialania. Np. przy duzej bazie drastycznie zwalnia, czy w przypadku zmiany to co napisalem powyzej (rozdzielenie) nie jest takie banalne jak sie teraz wydaje. No i generalnie czy nie przekombinowalem z ta tabela :)

Acha, aktualnie mam 8 widokow korzystajacych z tej bazy we wspomniany sposob, po zakonczeniu projektowania bazy powinno ich byc 12-14.

0

jeśli jesteś pewny, że nie będzie problemu z wpisaniem kilku wartości z takim samym ContentType to powinno być OK.
Co do późniejszej zamiany na kilka tabel to problem zawsze jest bo tam, gdzie kiedyś odwoływałeś się do tabeli a teraz będzie trzeba do tabeli b.
Natomiast jeśli chodzi o ilość danych to większość baz spokojnie sobie poradzi z kilkudziesięcioma tysiącami rekordów w tabeli, o ile oczywiście będziesz miał odpowiednio założone indeksy

0

Z zamiana nie powinno byc problemu, bo usuwam istniejacy widok, korzystajacy z tej tabeli, tworze nowa tabele o tej samej nazwie co widok, ktora i tak bedzie miala te same kolumny (+ ew. dodatkowe) i aplikacja nie powinna zauwazyc roznicy.

Aplikacja bedzie hulac na mssql, wiec raczej bedzie szybko :) Ale upewniam sie, ze sie nie zdziwie za pol roku ;)

Dzieki za opinie :)

0

Jeśli będziesz wybierał z tej tabeli po jednym lub kilka rekordów (używając indeksu), to liczba rekordów w tabeli praktycznie nie ma znaczenia. Wyszukiwanie w indeksie B-drzewa (MySQL) jest operacją o złożoności O(log(n)), o b. dużej podstawie logarytmu. W praktyce można przyjąć złożoność const. Więc czy 10 czy milion rekordów, problemu nie będzie.

0

To jest po kilka, kilkanascie wartosci dla jednego ContentType i CompanyID (glownie comboboxy w interfejsie), wiec bedzie tak jak mowisz :)

0
Krolik napisał(a)

W praktyce można przyjąć złożoność const. Więc czy 10 czy milion rekordów, problemu nie będzie.
przy select ale im więcej rekordów tym wolniejszy insert/delete i jeśli zmienia pola indeksowane to update

0

Na tabeli bedzie glownie select. Jezeli insert/update to jeden rekord na raz, wiec to bedzie nieodczuwalne chyba.

0
Misiekd napisał(a)
Krolik napisał(a)

W praktyce można przyjąć złożoność const. Więc czy 10 czy milion rekordów, problemu nie będzie.
przy select ale im więcej rekordów tym wolniejszy insert/delete i jeśli zmienia pola indeksowane to update

Insert/delete nie musi być wcale silnie zależny od liczby rekordów w bazie. Powyżej pewnego progu nie ma znaczenia, i tak potrzebne jest pełne (dalekie) pozycjonowanie głowic, i tak. Powiem nawet że wstawienie 2 rekordów do tabeli często trwa tyle samo co wstawienie jednego, no chyba, że są to jakieś koszmarnie wielkie rekordy i nie mieszczą się oba w jednym bloku. Natomiast ze zwiększonym kosztem modyfikacji danych (insert, update, delete) spowodanym indeksami zawsze trzeba się liczyć, ale znowu, większy wpływ ma liczba indeksów (liniowy) niż ilość indeksowanych danych (logarytmiczny). Ale w tym pzypadku, skoro mają być głównie selecty, to nie widzę problemu.

0

miałem na myśli aktualizację drzewa indeksów a nie samo wstawianie danych do plików

0

No to jak powiedziałem, liczba indeksów ma większy wpływ niż liczba rekordów już zaindeksowanych. Indeksy B drzewiaste typowo mają 3 poziomy, przy b. dużej ilości danych 4 poziomy - liczba rekordów praktycznie nie ma znaczenia dla czasu aktualizacji indeksu. Korzeń drzewa mieści się w cache i czasem nawet jakaś część drugiego poziomu, więc dostęp do indeksu to 2 lub 3 operacje WE/WY, aktualizacja to 3-6 op. WE/WY. Jeśli użyjesz indeksów hashujących to liczby te są jeszcze mniejsze i jeszcze bardziej niezależne od ilości danych.

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