=?iso-8859-2?q?Relacje_uwzgl=EAdniaj=B1ce_czas_(jak=3F)?=
superfis@poczta.fm - 20-05-2006 00:04
=?iso-8859-2?q?Relacje_uwzgl=EAdniaj=B1ce_czas_(jak=3F)?=
Witam wszystkich,
Od dłuższego kawałka czasu szukam właściwej techniki powiązania tabel z uwzględnieniem zmian w nich dokonywanych.
Mamy:
TAB1 ---------- id integer (PK) name text
TAB2 ---------- id integer (PK) address text tab1_id integer (FK do tabeli tab1)
Przy takim układzie jak powyżej mamy fajną relację jeden-do-wiele pomiędzy TAB1 i TAB2, tyle, że podczas zmiany pola 'address' w TAB2 nigdy już sie nie dowiemy jaki był to adres sprzed tej zmiany.
Wykombinowałem sobie, że może taki układ dałby możliwość zachowania relacji na każdy moment czasu w przeszłości:
TAB1 ---------- id integer (PK) name text dateFrom date dateTo date
TAB2 ---------- id integer (PK) address text tab1_id integer (FK do tabeli tab1) dateFrom date dateTo date
Podczas zmiany jednego z adresow nie idzie UPDATE tylko INSERT z nową data obowiązywania (dateFrom i ewentualnie dateTo), a odpytywanie bazy o nazwisko i adres na konkretny stan w czasie (czyli na konkretną datę) wyglądałoby jakoś tak:
konkretny stan w czasie reprezentuje zmienna someDate
select t1.name, t2.address from tab1 t1, tab2 t2 where t1.id = t2.tab1_id and t1.dateFrom in ( select max (dateFrom ) from tab1 where t1.id = id and someDate between dateFrom and dateTo group by dateFrom ) and t2.dateFrom in ( select max (dateFrom ) from tab2 where t1.id = tab1_id and someDate between dateFrom and dateTo group by dateFrom )
To działa, jednak skomplikowanie zapytania jest zbyt wielkie w stosunku do osiąganego rezultatu, a o wydajności lepiej nawet nie wspomnę.
Powracając do pytania... czy wie ktoś jak problem relacji w funkcji czasu należy rozwiązać aby było to rozwiązanie przyjemne i w miarę wydajne? Może są jakieś patterny?
Pozdrawiam i mam nadzieje na jakies sugestie, Sławek
Mikolaj Rydzewski - 20-05-2006 00:04
superfis@poczta.fm wrote:
> Powracając do pytania... czy wie ktoś jak problem relacji w funkcji > czasu należy rozwiązać aby było to rozwiązanie przyjemne i w > miarę wydajne? Może są jakieś patterny?
Wersjonowanie rekordow? Mozna zrobic triggerem.
-- Mikolaj Rydzewski
=?ISO-8859-2?Q?Micha=B3?= Kuratczyk - 20-05-2006 00:04
superfis@poczta.fm wrote: > Powracając do pytania... czy wie ktoś jak problem relacji w funkcji > czasu należy rozwiązać aby było to rozwiązanie przyjemne i w > miarę wydajne? Może są jakieś patterny? W Oracle służy do tego Workspace Manager. Można sobie zrobić tak:
SQL> create table ceny (id number primary key, cena number);
Table created.
SQL> exec dbms_wm.EnableVersioning('ceny', 'VIEW_WO_OVERWRITE');
PL/SQL procedure successfully completed.
SQL> insert into ceny values (1, 1);
1 row created.
SQL> update ceny set cena=2 where id=1;
1 row updated.
SQL> update ceny set cena=3 where id=1;
1 row updated.
SQL> column created format a20 SQL> column retired format a20 SQL> select id, cena, type_of_change, to_char(createtime,'dd-mon hh24:mi:ss') created, 2 to_char(retiretime,'dd-mon hh24:mi:ss') retired from ceny_hist;
ID CENA TYP CREATED RETIRED ---------- ---------- --- -------------------- -------------------- 1 1 I 19-may 16:00:45 19-may 16:00:57 1 2 U 19-may 16:00:57 19-may 16:01:02 1 3 U 19-may 16:01:02
Procedura dbms_wm.EnableVersioning zmienia nazwę tabeli i dodaje do niej kolumny, w których przechowywane są te dodatkowe informacje, a następnie tworzy widok o takiej nazwie jaką miała tabela (dzięki czemu dla aplikacji jest to zupełnie przezroczyste) oraz kilka innych widoków pozwalających w łatwy sposób dobierać się do tych dodatkowych informacji (tak jak ceny_hist w tym wypadku). Jeśli takie rozwiązanie Ci odpowiada, a nie używasz Oracle, to poczytaj w dokumentacji jak to działa, albo potestuj sobie sam na Oracle, a potem zaimplementuj u siebie.
-- Michał Kuratczyk
=?ISO-8859-2?Q?Pawe=B3_Matejski?= - 20-05-2006 00:04
superfis@poczta.fm wrote: > Witam wszystkich, > > Od dłuższego kawałka czasu szukam właściwej techniki powiązania > tabel z uwzględnieniem zmian w nich dokonywanych. > > Mamy: > > TAB1 > ---------- > id integer (PK) > name text > > TAB2 > ---------- > id integer (PK) > address text > tab1_id integer (FK do tabeli tab1) > > Przy takim układzie jak powyżej mamy fajną relację jeden-do-wiele > pomiędzy TAB1 i TAB2, tyle, że podczas zmiany pola 'address' w TAB2 > nigdy już sie nie dowiemy jaki był to adres sprzed tej zmiany. > > Wykombinowałem sobie, że może taki układ dałby możliwość > zachowania relacji na każdy moment czasu w przeszłości: > > > TAB1 > ---------- > id integer (PK) > name text > dateFrom date > dateTo date > > TAB2 > ---------- > id integer (PK) > address text > tab1_id integer (FK do tabeli tab1) > dateFrom date > dateTo date > > Podczas zmiany jednego z adresow nie idzie UPDATE tylko INSERT z nową > data obowiązywania (dateFrom i ewentualnie dateTo), a odpytywanie bazy > o nazwisko i adres na konkretny stan w czasie (czyli na konkretną > datę) wyglądałoby jakoś tak: > > konkretny stan w czasie reprezentuje zmienna someDate > > > select t1.name, t2.address > from tab1 t1, tab2 t2 > where t1.id = t2.tab1_id > and t1.dateFrom in ( > select max (dateFrom ) > from tab1 > where t1.id = id > and someDate between dateFrom and dateTo > group by dateFrom ) > and t2.dateFrom in ( > select max (dateFrom ) > from tab2 > where t1.id = tab1_id > and someDate between dateFrom and dateTo > group by dateFrom ) > > To działa, jednak skomplikowanie zapytania jest zbyt wielkie w > stosunku do osiąganego rezultatu, a o wydajności lepiej nawet nie > wspomnę. > > Powracając do pytania... czy wie ktoś jak problem relacji w funkcji > czasu należy rozwiązać aby było to rozwiązanie przyjemne i w > miarę wydajne? Może są jakieś patterny?
Problem jest skomplikowany. :) Jeśli potrzebujesz tylko stan dla jakiegoś momentu w czasie, to wystarczy chyba: where t1.id = t2.tab1_id and someDate between t1.dateFrom and t1.dateTo and someDate between t2.dateFrom and t2.dateTo
Ale zachowanie spójności danych standardowymi mechanizmami bazodanowymi w takim przypadku nie da się zrobić. Ale zastanów się, czy na pewno potrzebny jest Ci stan z danego momentu. Może wystarczy tylko historia zmian? Takie cos dużo łatwiej oprogramować w kliencie.
-- P.M.
Artur Muszynski - 20-05-2006 00:04
=?iso-8859-2?Q?Re:_Relacje_uwzgl=EAdniaj=B1ce_czas_=28jak=3F= 29?=
> Od dłuższego kawałka czasu szukam właściwej techniki powiązania > tabel z uwzględnieniem zmian w nich dokonywanych.
Ja znalazłem artykuł o Bitemporal Storage Structure. Trochę skomplikowane, ale jak znajdziesz, to możesz poczytać.
artur
superfis@poczta.fm - 23-05-2006 00:25
=?iso-8859-2?q?Re:_Relacje_uwzgl=EAdniaj=B1ce_czas_(jak=3F)?=
Dziękuję Wam za propozycje rozwiązań.
Faktycznie z zapytaniem, które podałem w treści poprzedniej wiadomości, trochę przesadziłem :) - propozycja podana przez Pawła Matejskiego wystarcza.
Mój problem jest o tyle dodatkowo skomplikowany, ze bazę danych chcę "przykryć" Hibernate'm, co skutecznie uniemożliwi mi jak sądze zastosowanie rozwiązania Oracle'owego (jeszcze nie wiem nic na temat Bitemporal Storage Structures).
Zdaje się, że pochylę się nad rozwiązaniem zmodyfikowanym przez Pawła Matejskiego i w połączeniu z trigerami na tabelach zobaczę czy uda się je dostosować do wymagań Hibernate.
Dziękuję serdecznie za wszelkie odpowiedzi!
Pozdrawiam, Sławek
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
Wydajność baz danych w zależności od poziomu izolacji ANSI/ISO
Czy zna (obsługuje) ktoś program Iso Draw ?
MYSQL - kodowanie w ISO-PL
strona plus baza w iso do utf-8
Kodowanie: z iso na utf
Jak =?windows-1250?Q?pobra=E6_szacowan=B9_wielko=9C=E6_zbiory_wy nikowego_w_MS?==?windows-1250?Q?_SQL_2005=3F?=
=?UTF-8?Q?=5Bmysql=5D_jak_pobra=C4=87_warto=C5=9B=C4=87_ AUTO=5F?==?UTF-8?Q?INCREMENT=3F?=
Konwesja znaków w dump'ie bazy danych - ISO -> utf-8 -> ISO -> utf-8
=?iso-8859-2?q?Co_oznacza_b=B3=B1d_Warning:_mysql=5Fconnect() _[function.mysql-connect]:_Can't_connect_to_local_MySQL_server_through_sock et_'/var/run/mysqld/mysqld.sock'_(2)_in?=
=?iso-8859-2?q?Informatyka,_Java,_EJB,_Ajax,_Spring=2E_Czy=BF by_to_koniec_=B6wiata,_czy_te=BF_nasze_uczelnie_b= EAd=B1_uczy=B3y_w_ko=F1cu!_czego_praktycznego_=2E= 2E=2E=2E?=
zanotowane.pldoc.pisz.plpdf.pisz.plshanti.opx.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|