🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.bazy-danych
Article #194107

Re: PostgreSQL - jak najlepiej definiować dynamiczne pola?

#194107
From: Marek
Date: Mon, 09 Feb 2015 22:36
138 lines
8423 bytes
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
Technical Details
Message-ID: <mbbcop$3il$1@news.icm.edu.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!.POSTED!not-for-mail
References: <mag0cl$o93$1@news.icm.edu.pl> <slrnmcqmva.5h7.tom@tv2.dom.local> <makuln$8ps$1@news.icm.edu.pl> <00393f98-4afb-4213-934d-9156200c7bcb@googlegroups.com> <mavv3h$n7l$1@news.icm.edu.pl> <8e718611-b061-4aaa-9fb0-1687681dcb94@googlegroups.com> <mb25li$mon$1@news.icm.edu.pl> <f6a66af6-182a-47d7-a297-7a1b998ebee2@googlegroups.com> <mb2g3c$isp$1@news.icm.edu.pl> <e64d3758-bdb8-4f73-b75a-3aa9b5f789e6@googlegroups.com> <54d5e7a7$0$2188$65785112@news.neostrada.pl> <1e428ab3-3e7f-4a50-a7b0-d5d458ad2a65@googlegroups.com> <54d66936$0$2206$65785112@news.neostrada.pl> <89a37815-f4ab-423f-bdc8-13ff32bb4f7e@googlegroups.com> <ac14966e-c0e4-498b-9257-25d1e6363d0b@googlegroups.com> <mbahen$9em$1@news.icm.edu.pl> <54d8f45a$0$2214$65785112@news.neostrada.pl>

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!.POSTED!not-for-mail
From: Marek <precz@spamowi.com>
Newsgroups: pl.comp.bazy-danych
Subject: Re: PostgreSQL - jak najlepiej definiować
 dynamiczne pola?
Date: Mon, 09 Feb 2015 23:36:07 +0100
Organization: ICM, Uniwersytet Warszawski
Lines: 138
Message-ID: <mbbcop$3il$1@news.icm.edu.pl>
References: <mag0cl$o93$1@news.icm.edu.pl> <slrnmcqmva.5h7.tom@tv2.dom.local> <makuln$8ps$1@news.icm.edu.pl> <00393f98-4afb-4213-934d-9156200c7bcb@googlegroups.com> <mavv3h$n7l$1@news.icm.edu.pl> <8e718611-b061-4aaa-9fb0-1687681dcb94@googlegroups.com> <mb25li$mon$1@news.icm.edu.pl> <f6a66af6-182a-47d7-a297-7a1b998ebee2@googlegroups.com> <mb2g3c$isp$1@news.icm.edu.pl> <e64d3758-bdb8-4f73-b75a-3aa9b5f789e6@googlegroups.com> <54d5e7a7$0$2188$65785112@news.neostrada.pl> <1e428ab3-3e7f-4a50-a7b0-d5d458ad2a65@googlegroups.com> <54d66936$0$2206$65785112@news.neostrada.pl> <89a37815-f4ab-423f-bdc8-13ff32bb4f7e@googlegroups.com> <ac14966e-c0e4-498b-9257-25d1e6363d0b@googlegroups.com> <mbahen$9em$1@news.icm.edu.pl> <54d8f45a$0$2214$65785112@news.neostrada.pl>
NNTP-Posting-Host: 89-69-222-145.dynamic.chello.pl
Mime-Version: 1.0
X-Trace: news.icm.edu.pl 1423521369 3669 89.69.222.145 (9 Feb 2015 22:36:09 GMT)
X-Complaints-To: usenet@news.icm.edu.pl
NNTP-Posting-Date: Mon, 9 Feb 2015 22:36:09 +0000 (UTC)
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0
In-Reply-To: <54d8f45a$0$2214$65785112@news.neostrada.pl>
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit