Obiektowe Bazy Danych Paweł Ciach Plan prezentacji: • Oczekiwania wobec Obiektowych Baz Danych • Język Obiektowych Baz Danych • Trochę o formalnych ramach struktury i zachowania • Dostępne standardy • Dlaczego Obiektowe Bazy Danych się nie przyjęły • Alternatywne podejścia do zagadnienia • Bazy semi-strukturalne • Mapowanie R/O • Inne Oczekiwania wobec OBD W RDBMS brakuje nam: • Atrybutów złożonych - składowe atrybutów trzeba deklarować indywidualnie jako atrybuty relacji (np. Adres osoby) • Atrybutów zbiorowych - trzeba je reprezentować w innym schemacie relacyjnym (np. Podwładni osoby) • Agregacje i specjalizacje - konieczność posługiwania się indywidualnym schematem relacyjnym ze specjalnymi więzami integralności (np. Pracownik jest Osobą, albo Pracownik ma kierowcę) • Gdy nie ma możliwości dobrania klucza głównego wśród atrybutów, trzeba dokładać klucz sztuczny • Niezgodność impedancji (Technologiczna i kulturowa) Oczekiwania wobec OBD Przykład: Chcemy zamodelować przedsiębiorstwo produkujące samochody. Model musi spełniać następujące warunki: • firma ma nazwę, centralę, kilka oddziałów i dyrektora. • oddziały mają nazwę, biuro, kierownika i pracowników. • pojazdy mają nazwę modelu, kolor i producenta. • samochody mają nadwozie i napęd. Napęd ma silnik i skrzynię biegów. Silnik ma ilość koni i pojemność. • osoby mają nazwisko, wiek, miejsce zamieszkania i prywatny tabor. • pracownicy to osoby ze specyficznymi kwalifikacjami, wynagrodzeniem i z rodziną. Oczekiwania wobec OBD Jak to można zamodelować relacyjnie (pomijając pewne elementy): Firma IDFirmy INT NOT NULL Nazwa VARCHAR NOT NULL Ulica VARCHAR NOT NULL Miejscowosc VARCHAR NOT NULL Dyrektor INT NOT NULL PRIMARY KEY (IDFirmy) FOREIGN KEY (Dyrektor) REFERENCES Pracownik (NrPrac) Oddział IDFirmy INT NOT NULL NazwaOddz VARCHAR NOT NULL Ulica VARCHAR NOT NULL Miejscowosc VARCHAR NOT NULL Kierownik INT NOT NULL PRIMARY KEY (IDFirmy,NazwaOddz) FOREIGN KEY (IDFirmy) REFERENCES Firma FOREIGN KEY (Kierownik) REFERENCES Pracownik (NrPrac) PracOddz IDFirmy INT NOT NULL NazwaOddz VARCHAR NOT NULL Prac INT NOT NULL PRIMARY KEY (IDFirmy, NazwaOddz, Prac) FOREIGN KEY (IDFirmy) REFERENCES Firma FOREIGN KEY (NazwaOddz) REFERENCES Oddział FOREIGN KEY(Prac) REFERENCES Pracownik (NrPrac) Osoba NrOsoby INT NOT NULL Nazwisko VARCHAR NOT NULL ... Pracownik NrPrac INT NOT NULL Nazwisko VARCHAR NOT NULL ... FOREIGN KEY (NrPrac) REFERENCES Osoba (NrOsoby) Oczekiwania wobec OBD Teraz zróbmy na naszym modelu danych zapytanie: Szukamy pracowników o nazwisku Kowalski zatrudnionego w oddziale Gliwice firmy GM: SELECT NrPrac FROM Firma, Oddział, PracOddz, Pracownik WHERE Firma.Nazwa = ‘GM’ AND Firma.IDFirmy = Oddział.IDFirmy AND Oddział.Miejscowość = ‘Gliwice’ AND Oddział.IDFirmy = PracOddz.IDFirmy AND Oddział.NazwaOddz = PracOddz.NazwaOddz AND PracOddz.Prac = Pracownik.NrPrac AND Pracownik.Nazwisko = ‘Kowalski’; Oczekiwania wobec OBD A jak można sobie wyobrazić modelowanie tego w OBD - poniżej odpowiednie klasy: Firma: [ Oddział: [ Adres: [ Nazwa : String, Nazwa : String, Ulica : String, Centrala : Adres, Biuro : Adres, Miejscowość : String ] Oddziały: { Oddział }, Kierownik : Pracownik, Dyrektor: Pracownik ] Pracownicy : { Pracownik } ] Osoba: [ Pracownik is-a Osoba: [ Nazwisko : String, Kwalifikacje: { String } Wiek : Integer, Wynagrodzenie : Integer MiejsceZam : Adres, Rodzina : { Osoba } ] Tabor : { Pojazd } ] Oczekiwania wobec OBD Teraz zróbmy teraz zapytanie na obiektowym modelu zapytanie, używając obiektowej adaptacji SQLa: Znowu szukamy pracowników o nazwisku Kowalski zatrudnionego w oddziale Gliwice firmy GM: select e from e in Pracownik, c in Firma, s in Oddział where c.Nazwa = ‘GM’ and s in c.Oddziały and s.Biuro.Miejscowość = ‘Gliwice’ and e in s.Pracownicy and e.Nazwisko = ‘Kowalski’; Oczekiwania wobec OBD To były cechy związane z aspektami strukturalnymi OBD. Ale to jeszcze nie wszystko: Aspekt behawioralny - chcemy mieć to co jest w innych językach obiektowych: • Enkapsulacja - chcemy mieć możliwość tworzenia abstrakcyjnych typów danych. Do klasy można przydzielać metody. Z zewnątrz zachowanie jest widoczne jako zbiór sygnatur. • Przeciążanie, przesłanianie i późne wiązanie Oczywiście, chcemy też mieć to co mamy w RDBMSach: • Trwałość - i rozróżnianie obiektów trwałych i ulotnych, • Kontrola przy pracy wielu użytkowników (Transakcje powinny być ACID - Atomically, Consistency, Isolated, Durable) - w pewnym stopniu problemem mogą być tutaj metody. • Zarządzanie pamięcią pomocniczą, odtwarzanie Języki OBD Na kolejnych przykładach będziemy budować podobny do SQL język OBD tak żeby zrozumieć jakie cechy powinien mieć taki język. Proste wybieranie obiektów. OIDs - identyfikatory obiektów (jak referencje) - do wykorzystania w dalszym przetwarzaniu: select f from f in Pojazd where model = ‘Vectra’; Natomiast wszystkie atrybuty obiektu uzyskamy wykonując: select * from Pojazd where model = ‘Vectra’; Języki OBD Wyrażenia ścieżkowe. Proste: select * from Pojazd where kolor = ‘zielony’ and Producent.Nazwa = ‘Ford’; Można w klauzuli select: select Dyrektor.Wynagrodzenie from Firma where Centrala.Miejscowosc = ‘Rzym’ W klauzuli where: select * from Firma where Centrala = = Dyrektor.MiejsceZam Uwaga: ‘= = ‘ identyczność obiektów (OIDów), a nie wartości. Jak chcemy porównać miejscowość, to już nie można użyć ‘= = ‘: select * from Firma where Centrala.Miejscowość = Dyrektor.MiejsceZam.Miejscowość; Zmienne w wyrażeniu ścieżkowym: select Tabor[x].Napęd.Silnik.Moc from Pracownik where x in Samochód Języki OBD Jawne złączanie: select p,f from p in Osoba, f in Pojazd where P.Nazwisko = f.producent.Dyrektor.Nazwisko; Metody: select a1, a2 from a1 in Pracownik, a2 in Pracownik where a1.Zastępca (a2); select Wiek from Osoba where Nazwisko = ‘Kowalski’ Języki OBD Zbiory obiektów. Odpowiednik perspektyw: MojaRodzina := select p from Osoba where Nazwisko = ‘Kowalski’ select Nazwisko from MojaRodzina where Wiek > 50 Podzapytania: select Nazwa from (select Producent from Pojazd where Kolor = ‘niebieski’) select count(f) from f in Firma where Dyrektor in (select a from a in Pracownik where Wynagrodzenie > 200 000) Języki OBD Problem: zbiory zbiorów Weźmy: select f.Oddziały.Pracownicy.Wynagrodzenie from f in Firma W wyrażeniu ścieżkowym nie możemy zastosować atrybutu Pracownicy do wyniku f.Oddziały, bo ten ostatni jest zbiorem - powstaje błąd typu. Możliwe obejście - jawne usunięcie zagnieżdżenia za pomocą operatora spłaszczenia: flatten(select flatten ( flatten (f.Oddziały).Pracownicy).Wynagrodzenie from f in Firma) Języki OBD Dziedziczenie. Nazwisko w Pracownik zostało odziedziczone z Osoba. select Kwalifikacje from Pracownik where Nazwisko = ‘Kowalski’ Szukamy tych osób które mają ponad 50 lat i nie są pracownikami. select * from p in Osoba where Wiek > 50 and p not in Pracownik Trochę o formalizmach Mamy schemat struktury (Scstruct) i zachowania (Scbehaw). Opowiem tylko o tym pierwszym. Całość wygląda to mniej więcej tak: Trochę o formalizmach T - Type, indukcyjnie: • prymitywy należą do T • Krotka: [A1:t1..An:tn] należy do T o ile Ai to różne atrybuty, i ti należą do T (typ krotkowy) • {t} należy do T jeżeli t należy do T (typ zbiorowy) Values - poprzez dom: • dom(prymityw) - wszystkie możliwe wartości prymitywu • dom([A1:t1..An:tn]) := ([A1:v1..An:vn] gdzie vi należy do dom (ti) • dom({t}) := ({v1..,vn} gdzie vi należy do dom(t)) Trochę o formalizmach Dokładamy klasy - kolejny warunek do Type: C jest podzbiorem T, gdzie C - skończony podzbiór nazw klas I analogiczne do Values: dom( c ) = OID dla każdego c należącego do C Mamy również hierarchię klas - częściowy porządek IsA na C, z klasą object taką, że dla każdego c należącego do C, c IsA object. Jeżeli c IsA c’, to c jest podklasą, c’ jest nadklasą. Równolegle, definiujemy porządek <= na Type (T), jako najmniejszy częściowy porządek zamknięty ze względu na reguły (any - odpowiednik object): • c IsA c’ => c <= c’ dla c,c’ należących do C • t=[A1:t1..An:tn], t’=[A1’:t1’..Am’:tm’] jeżeli n >= m i dla każdegoAi’:ti’ z t’ istnieje Aj:tj z t gdzie Ai’ = Aj i tj <= ti’, to będzie też t <= t’ • Jeżeli t <= t’ to rwnież {t} <= {t’} • t <= any dla każdego t należącego do T Trochę o formalizmach Schemat struktury to 3-ka: Scstruct = (C, IsA, type), gdzie C - sk. zb. nazw klas, type:C->T - przypisuje typ klasie. Schematy strukturalne są dobrze utworzone o ile: C IsA C’ implikuje type(C) <= type(C’) Teraz chcemy zbudować d(Scstruct) odzwierciedlając Scstruct. Obiekt - (o, v), gdzie o to identyfikator z Object, v wartość z Values. Przydzielmy obiekty do klas: Bazowe rozszerzenie: Przypisanie zbioru identyfikatorów obiektów do nazwy klas w C. Jeżeli o należy do inst( c) dla c należącego do C, to c nosi nazwę klasy bazowej dla o. Rozszerzenie dla odwzorowania inst, to Inst, które przypisuje zbiór identyfikatorów obiektów do nazw klas c należących do C, z uwzględnieniem hierarchii IsA: Inst( c ) = inst ( c ) {o|o inst (c’), c’ C, c’ IsA c} Np. inst(Object) = {}, Inst(Object) = {wszystkie obiekty} Trochę o formalizmach Teraz możemy zdefiniować sobie d(Scstruct) = (inst, val), gdzie inst jest bazowym rozszerzeniem, a val: Objects->Values, jest odwzorowaniem o własności: o inst( c), c C => val(o) dom (typ( c)) Classes C type inst Objects O Types T dom val Values V W tym modelu brakuje jeszcze ponownego używania atrybutów w klasach podrzędnych oraz dziedziczenia wartości domyślnych. Trochę o formalizmach A dlaczego brakuje? Rozważmy klasy Pracownik i Osoba: Pracownik IsA Osoba type(Osoba) = [ Nazwisko : string, ... ] type(Pracownik) = [Kwalifikacje: {string}, ...] Wydaje się, że jest dobrze - intuicyjnie, Pracownik powinien dziedziczyć atrybuty Osoba, ponieważ Pracownik IsA Osoba. Ale warunek dobrego utworzenia z definicji schematu strukturalnego - c IsA c’ => type( c) <= type (c’) nie jest spełniony - nie jest prawdą, że type(Pracownik) <= type(Osoba) Trzeba jeszcze: • poluzować warunek type( c) <= type (c’) definiując Type (Funkcja typu uwzględniająca dziedziczenie) • zająć się wartościami domyślnymi (Funkcja Val uwzględniająca wartości domyślne) • na koniec trzeba coś zrobić z konfliktami dziedziczenia - podając definicję schematu wolnego od konfliktów. • No i jeszcze schemat behawioralny... Standardy OBD Istotne są 2 standardy: • SQL3 - podejście obiektowo-relacyjne. • ODMG-93 - Object Database Management Group (podgrupa OMG) Ten drugi ma następujące cechy: • Model obiektu wywodzi się z ogólniejszego modelu OMG (wykorzystywany do implementacji CORBA) • Język definiowania obiektów (ODL) oparty o IDL • Język zapytań (OQL) - nie jest oparty o SQL3 • Ma powiązania do obiektowych języków programowania (w szczególności do Smalltalka, C++, Javy). Obiektowe bazy danych przegrały bo • Relacyjne bazy danych mają potężną reprezentację na rynku. SZBD są rozwiązaniami stabilnymi, przetestowanymi i działającymi od lat. Wydano olbrzymie ilości środków w rozbudowę tych narzędzi - są to w tej chwili jedne z najbardziej skomplikowanych aplikacji. • Firmy produkujące bazy danych zdecydowały na model obiektoworelacyjny. Tak naprawdę (przynajmniej w początkowej fazie) to był tylko marketingowy buzzword - ale z pewnością zniechęciło to sporą grupę osób do obiektowych bazy danych. • Pojawił się model przetwarzania wielowarstwowego. Oferowane przez ODB możliwości przetwarzania po stronie bazy danych straciły sens wobec używania application serverów w celu wykonywania scentralizowanych obliczeń. Alternatywy Podejście semi-strukturalne. Przykład: LORE • W przeciwieństwie do tradycyjnych modeli danych, gdzie narzuca się sztywny schemat danych, w przypadku baz semi-strukturalnych struktura jest elastyczna, • Reprezentacja danych - etykietowany graf skierowany, • Elastyczne języki zapytań potrafiące obsługiwać nieregularności struktury danych, • Gdy dane są nieregularne, w modelu relacyjnym w takim celu używa się null - brzydkie, nieprzyjemne i niewygodne, w obiektowych bazach dziedziczenie i typy złożone mogą pomóc - ale wciąż może być potrzebna większa elastyczność • Duże wyzwania implementacyjne - np. indeksowanie. Alternatywy Mapowanie obiektów na relacje. Kwestie do rozwiązania: • W najprostszym przypadku atrybuty klas mapują się na atrybuty tabel. Ale trzeba pamiętać o typach, • Mapowanie metod na atrybuty relacyjne, • Shadow information - wspominany już w kontekście OBD problem sztucznych kluczy głównych • Dziedziczenie - można: • Zmapować całą hierarchię na jedną tabelę • Zmapować wszystkie klasy nie-abstrakcyjne na tabelki • Zmapować wszystkie klasy na tabelki Dobrym pomysłem jest nie robić tego ręcznie, ale użyć automatu takiego jak hibernate. Alternatywy Dziedzina jest szeroka i atakowana z bardzo wielu miejsc. Technologie/rozwiązania związane z OBD obejmują: • XML - trochę podobny do semi-strukturalnych baz, ale są do dyspozycji potężne narzędzia do definicji schematu - DTD i XML-Schema. Bardzo szeroko wspierany. Istnieją bazy XML-owe - np. Tamino. XML ewoluował z zupełnie innego miejsca niż pozostałe technologie - od SGML, czyli języka stworzonego na potrzeby poligrafii. • JDO - Java Data Objects - przeźroczysta trwałość obiektów. • Technologie pokroju EJB (warto przyjrzeć się EJB Query Language adaptacji OQL), CORBA, DCOM, Web services - wszystkie dostarczają dodatkową warstwę abstrakcji ukrywając logikę biznesową. W szczególności może oznaczać to obiektową reprezentację bazy danych. Bibliografia • Lausen Georg, Vossen Gottfried, Obiektowe bazy danych, WNT 2000 • http://www.db.ucsd.edu/cse132B/FormalODB.pdf • http://www.agiledata.org/essays/mappingObjects.html • http:// www.hibernate.org • http://www-db.stanford.edu/lore • http:// www.w3c.org