W dniu 2015-02-09 o 18:54, wloochacz pisze:
>> b) W dynamicznie dostawianych polach w tabeli właściwej (tzn.
>> zawierającej dane, które rozszerzamy o dodatkowe pola) z narzuceniem
>> typu pól i budowaniem na nich indeksów gdzie trzeba.
>>
>> To wtedy nie ma problemu w tworzeniu relacji. Aczkolwiek dynamiczne
>> dostawianie pól to nie jest profesjonalne podejście...
> Uzasadnij, bo mam dokładnie odwrotne wyobrażenie.
Uzasadnić to, że nie jest profesjonalnym podejściem iż żyjąca aplikacja
modyfikuje sobie sama strukturę bazy danych? Już raz cytowałem kolegę
Cezarego (2ga wypowiedź w wątku). Też mam pewne obiekcje.
> Tylko jest kilka ALE - nie wyobrażam sobie ręcznego zarządzania tym
> bajzlem. to musi być rozwiązane systemowo i automatycznie w taki sposób,
> aby raz dodane pole było widoczne dla całego systemu.
Żaden problem. Wiele lat stosowałem takie rozwiązanie. Ani razu nie
miałem problemów. Sama baza pilnuje siebie na poziomie triggerów i
plpgsql. Jedyna ALE jakie poza nie profesjonalnym podejściem jakie
doświadczyłem, to fakt, że przy dużej liczbie rekordów usuwanie (lub
dodawanie - już nie pamiętam) pól czy indeksów trwało bardzo długo, co
czasem kończyło się timeoutem PHP. Rozwiązałem to również ale tak czy
owak szukam lepszej metody.
> Bez rekompilacji systemu (albo zmiany kodów źródłowych w językach
> skryptowych - jeżeli ktoś się ma ochotę czepić...).
> Ale takie podejście przerasta większość "programistów".
> Sorry - taka prawda.
Niczego w kodach źródłowych nie zmieniałem. Mnie to nie przerosło a nie
jestem jakimś mega programistą :-) Przykładowo (z życia wzięte),
redaktor CMS zażyczył sobie dodać cechę lokalu (ma ogródek) w serwisie
WWW poświęconym deweloperce. Chciał aby dodanie tej opcji stanowiło od
razu kryterium wyszukiwania w części publicznej serwisu. Dodał nowe
pole, nazwał je, zaznaczył iż ma się w publicznej wyszukiwarce pojawić,
ustawił samodzielnie w lokalach, które mają ogródek a które nie i
aplikacja śmiga. Niczego nie musiałem doprogramowywać.
> Po drugie, nie każdemu takie podejście potrzebne. W realnym zastosowaniu
> okazuje się, że wykorzystanie paradygmatu EAV (doczytaj se w wikipedii
> czy gdzie tam chcesz co to, po co i na co) ze wszystkimi jego wadami
> daje po prostu radę.
Chodzi o wirusowe zapalenie tętnic u koni? :-D
Żartuję... ale coś takiego właśnie stosowałem, co miało swoje poważne
ograniczenia. Np. trudno jest budować indeksy i constrainty jeśli
wartości w tym modelu raz są datą, raz są liczbą, raz są tekstem. Stąd
mój były pomysł rozbudowy modelu EAV o dublowanie wartości w tabelach.
Ale o tym dalej bo zaciekawiło mnie co napisałeś.
> I od tego bym na Twoim miejscu zaczął, skoro dla Ciebie "ogromna" baza
> danych ma 100 tabel ;-)
A tak, dla mnie to już ogromna :-)
>> Na wszelki wypadek zobrazuję co mam na myśli. Jakaś tabela, powiedzmy,
>> 1. W tabeli dodatkowych pól powstaje pole D, jego opisy etc.
> W EAV nie dodaje się pola, tylko wiersz do tabeli definicji pola.
> Na jego poziomie definiujesz nazwę, typ danych, constraint i link do
> relacji/obiektu biznesowego. Ja bym jeszcze dodał flagę określającą, czy
> dana wartość jest skalarna czy wektorowa.
... i tu jest to "dalej" o jakim wyżej wspominam.
Też tak kombinuję ale utknąłem właśnie na budowaniu constraintów.
Posłużmy się tabelami jak tu aby łatwiej było rozmawiać:
http://programowanie.opole.pl/archives/1692
słabo się to rozwiązanie nadaje bo entity_id nie określa o jaką tabelę
chodzi. Tabel typu "entities" może być wiele. Tak więc values musi mieć
jedno pole więcej do identyfikacji o jaką tabelę chodzi. Powiedzmy
byłoby to pole typu wyliczeniowego (to mi wystarczy) entity_name. No i
teraz jak zbudować constraint między parą entity_id/entity_name wiążący
którąś z kilku tabel entities1, entities2 ...
Czyli entity_id ma się odnosić do entity1 gdy pole entity_name zawiera
entity1. Ale to samo entity_id może się odnosić do każdej innej tabeli
również.
A po drugie, usprawniłbym tabelę values o różne reprezentacje wartości:
TEXT, INT, DATETIME, FLOAT i być może coś jeszcze. Typ atrybutu
określałby, które z tych pól reprezentuje wartość.Choć z drugiej strony
więcej niż jedno pole wartości atrybutu może strasznie utrudnić
programowanie aplikacji. Obawiam się tego bardzo.
Z kolei potrzebuję zindeksować pole wartości INT po to aby móc budować
na nim klucze obce. Trochę to skomplikowane zaczyna być.
>> 2. W tabeli wartości następuje skojarzenie w/w pola D z rekordem w
>> tabeli "dokument" i w uniwersalnym typie text pola "wartość" jest
>> przechowywana liczba oznaczająca ID użytkownika w tabeli userów. No ale
>> raczej kiepsko byłoby budować indeksowanie na polu tekstowym, które raz
>> jest liczbą a innym razem tekstem.
> Zależy.
> Ale po cholerę Ci indeks na tym polu?
Hmmm.. jeśli pole jest kluczem obcym, to wszędzie czytam, że zawsze
powinien być indeks na nim.
>> 3. Z w/w powodu dostawiamy pole danych D do tabeli "dokument" (lub
>> tabeli powiązanej poprzez dziedziczenie - inherit)
> Dziedziczenie w bazach relacyjnych? Ho, ho... można i tak, ale ja bym
> się w to nie bawił.
Miałem na myśli separację tabeli dynamicznie dostawianych pól od tabeli
"entities" posługując się nomenklaturą z linku. Wtedy możemy grzebać
jedynie w tabeli potomnej a zostawić w spokoju rodzica.
> Oczywiście są bazy post-relacyjne lub obiektowo-relacyjne, które
> zapewniają rożne wsparcie do takich zabawek (mam na myśli OOP w ujęciu
> bazo-danowym).
Mówimy o Postgresie wyłącznie.
> Moim zdaniem - nie warto. Więcej z tym kłopotów niż pożytku.
> Ale ja tam się na tym nie znam...
Bo ja wiem czy to takie zagmatwane? Zamiast robić SELECT * FROM document
robisz SELECT * FROM document_child. Zmieniasz tylko nazwę tabeli przy
SELECTach i nic się nie zmienia w kodzie. Dla porządku możesz też przy
UPDATE'ach, INSERT'ach - jak uznasz za stosowne.
> Constrainty (banał) i budowanie SQL (a tu zależy - może to być w miarę
> proste lub nie) możesz sobie załatwić po stronie aplikacji.
> Napiszesz to raz i będzie działało z dowolnym typem dokumentu.
> Tu nie ma co dywagować, tylko doczytać o EAV i zakodować.
> Do roboty! ;-)
Powoli mnie przekonujesz. Musimy tylko szczegóły dopracować. Mógłbym
oczywiście programowo tworzyć constrainty. Raczej zbudowałbym je w
plpgsql a nie w aplikacji. Baza niech pilnuje swojej integralności sama.
--
Pozdrawiam,
Marek