1 / 17

Języki i środowiska programowania systemów rozproszonych

Języki i środowiska programowania systemów rozproszonych. Wykład 9 Przetwarzanie struktur nieregularnych. Wykładowca : Tomasz Kowalski Wykłady przygotowane na podstawie materiałów prof. Kazimierza Subiety. Dane nieregularne (pół-strukturalne).

pearly
Download Presentation

Języki i środowiska programowania systemów rozproszonych

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Języki i środowiska programowania systemów rozproszonych Wykład 9 Przetwarzanie struktur nieregularnych Wykładowca: Tomasz Kowalski Wykłady przygotowane na podstawie materiałów prof. Kazimierza Subiety

  2. Dane nieregularne (pół-strukturalne) • Problem danych nieregularnych, zwanych również pół-strukturalnymi (semistructured) jest nowym sformułowaniem problemu wartości zerowych w bazach danych (NULL values). • Problem obrósł ogromną literaturą (ponad 500 pozycji) i w swoim czasie był ulubionym tematem licznych prac naukowych w kontekście tzw. „niekompletnej informacji”. • Powstały liczne prace dotyczące specjalnych algebr z wartościami zerowymi, specjalnych rachunków, trój-wartościowych i cztero-wartościowych logik, odpytywania „dysjunktywnej informacji” i zbiorów „możliwych światów”, i wiele innych. • Skrajnie mizerne rezultaty przy ogromnym nacisku badawczym. • Świat informatyki komercyjno-przemysłowej nie uznał więc tych rozwiązań za dostatecznie istotne; • Nie pojawiły się nawet próby implementacji czegokolwiek z tej góry poronionych pomysłów.

  3. Wartości zerowe w SQL • Problem wartości zerowych znalazł swoje odbicie praktyczne w SQL. • Sposób wprowadzenia wartości zerowych do SQL ignoruje zasadę korespondencji i wprowadza niespójności i rafy semantyczne. • W SQL wartość zerowa nie ma żadnej „zewnętrznej” semantyki, np. do reprezentowania niekompletnej informacji. • Jest to wyłącznie trik techniczny mający na celu dostarczenie projektantom i programistom możliwości uwzględnienia nieregularności w danych. • Projektant lub programista może go stosować do dowolnie wybranych celów, i on jest też jedynym autorytetem który wie, jaka jest zewnętrzna (biznesowa) semantyka wprowadzonych poprzez ten trik wartości zerowych.

  4. Trzy sposoby przetwarzania nieregularności • System typów danego uniwersalnego języka programowania (np. Java) przystosujemy w taki sposób, aby każdy wynik zapytania mógł być potraktowany jako poprawna wartość pewnego znanego w danym momencie typu. • Sposób ten jest mało realny ze względu na znaczne trudności koncepcyjne i implementacyjne dla programisty aplikacyjnego. • „Spłaszczenie” hierarchicznej struktury zwracanej przez zapytanie. • Przykładem takiego spłaszczenia jest potraktowanie całości wyniku wyszukiwania (łącznie z nazwami danych) jako ciągu bajtów a la XML. • Podobnym sposobem jest reprezentacja danych półstrukturalnych w dwóch lub więcej tabelach relacyjnych, gdzie wszystkie nazwy danych są trzymane jako stringi obok wartości, oraz istnieje specjalna tabela reprezentująca hierarchię danych.. • Zbudowanie nowego kompletnego środowiska programistycznego przystosowanego do przetwarzania danych półstrukturalnych. • Konieczność opracowania własnego języka programowania – trudne dla zastosowań komercyjnych, ale całkowicie możliwe w ramach prototypu lub własnego projektu.

  5. Przykład – „spłaszczenie” struktury XML <pracownik> <imie>Jan</imie> <imie>Adam</imie> <nazwisko>Kowalski</nazwisko> <data_urodz>1973-12-1</data_urodz> <adres> <miejscowosc> Warszawa </miejscowosc> <ulica> Sienna </ulica> <nr domu> 67 </nr domu> </adres> <pensja>2500</pensja> </pracownik> Części pliku XML Wartości Hierarchia NrCzęści NazwaCzęści 1 ”pracownik” 2 ”imie” 3 ”imie” 4 ”nazwisko” 5 ”data_urodz” 6 ”adres” 7 ”miejscowosc” 8 ”ulica” 9 ”nr domu” 10 ”pensja” NrCzęści Wartość 2 ”Jan” 3 ”Adam” 4 ”Kowalski” 5 ”1973-12-1” 7 ”Warszawa” 8 ”Sienna” 9 ”67” 10 ”2500” Nadczęść Podczęść 1 2 1 3 1 4 1 5 1 6 1 10 6 7 6 8 6 9

  6. Nieregularne dane w modelach składu AS0-AS3 • Wprowadzone przez nas modele składu AS0-AS3 z definicji są przygotowane do przechowywania dowolnych struktur nieregularnych. • Podobnie jak w XML, nie wprowadzamy także wartości zerowych, uważając że jeżeli wartość pewnego (pod-) obiektu jest nieznana lub nierelewantna, to taki (pod-) obiekt może być w całości pominięty w danym składzie obiektów. • Jak dotąd nie wiążemy modeli składu z jakimkolwiek systemem typów. • Mechanizmy wiązania na stosie środowiskowym nie zależą od tego, czy dane mają regularny format, czy są nieregularne. • W istocie jednak, ta swoboda jest pozorna i wynika wyłącznie z faktu, że przy konstrukcji semantyki języka zapytań pominęliśmy schemat danych, i to zarówno od strony znaczenia danych w dziedzinie przedmiotowej (dziedzinie biznesu) oraz od strony rozumienia wszelkich aspektów logicznej organizacji i reprezentacji danych. • Dobrym wzorcem w tym zakresie jest DTD oraz XMLSchema należące do technologii XML. • W systemie Loqis zrealizowaliśmy nieco inny model oparty o gramatyki bezkontekstowe i wyrażenia regularne.

  7. Konstrukcje w jęz. zapytań dla danych nieregularnych • Jeżeli dana o nazwie n jest nieobecna w pewnym obiekcie z identyfikatorem i, wówczas nested(i) nie będzie zawierać bindera o nazwie n. • Jeżeli mamy zapytanie o postaci q1 θ q2(n) gdzie q1zwraca identyfikator i, θ jest operatorem nie-algebraicznym, q2(n), jest zapytaniem zawierającym nazwę n (nie objętą innym operatorem nie-algebraicznym), • to w tej sytuacji odpowiedniego bindera nie ma na stosie, wobec czego nazwa n nie może być związana. • W tej sytuacji należy przyjąć, że wiązanie nazwy n zwróci pusty zbiór. • Powstaje pytanie, co z takim pustym zbiorem programista może zrobić.

  8. Przykład z pustym zbiorem • Rozważmy przykład: PracwhereZar > 1000 przy czym atrybut Zar może nie wystąpić w niektórych obiektach Prac. • W tej sytuacji można przyjąć, że jeżeli Zar nie wystąpi, to predykat Zar > 1000 przyjmuje wartość fałsz. • Alternatywnie można przyjąć, że jest to sytuacja błędna powodująca podniesienie wyjątku. • Pierwsze założenie prowadzi do licznych niespójności (identycznych z tymi, które były przyczyną krytyki wartości zerowych), zatem je bezwzględnie odrzucamy. • Pozostaje tylko druga interpretacja, czyli przyjęcie, że zapytanie to jest błędne.

  9. Jak powinien postąpić programista? • Jeżeli programista oczekuje, że atrybut Zar może nie istnieć, to powinien tę sytuację przewidzieć w swoim zapytaniu. • Np. przyjmując, że count działa również na indywidualnych elementach zwracając dla nich 1, może formułować to zapytanie w sposób następujący: (Pracwherecount(Zar) = 1 ) whereZar > 1000 (Pracwhereexists(Zar) ) whereZar > 1000 • Najpierw sprawdza, czy Zar istnieje, następnie upewniwszy się, że istnieje, używa po where odpowiedniego predykatu. • Zwrócimy uwagę, że w tej sytuacji nie byłoby poprawne pozornie identyczne zapytanie: Pracwhereexists(Zar) andZar > 1000 gdyż wymagałoby to specjalnego trybu ewaluacji operatora and (drugi człon nie podlegałby ewaluacji jeżeli pierwszy człon zwróciłby false). • W językach zapytań taka interpretacja mogłaby prowadzić do błędów ze względu na optymalizację zapytań, która w wyniku metod przepisywania może przestawić kolejność predykatów.

  10. Sposób z kwantyfikatorem • Analogicznie, przyjmując, że kwantyfikatory działające na indywidualnym elemencie traktują go jako zbiór jedno-elementowy, można to samo zapytanie sformułować z pomocą kwantyfikatora: PracwhereZarasz (z > 1000) • Zapytanie zwraca referencje do obiektów pracowników, którzy mają zarobek i przekracza on 1000. PracwhereZarasz (z > 1000) • Zapytanie, oprócz w/w referencji, zwraca także referencje do tych obiektów Prac, w których atrybut Zar jest nieobecny (kwantyfikator ogólny działający na pustym zbiorze zawsze zwraca prawda). • Jak widać, dane nieregularne w SBQL nie wymagają wprowadzania wartości zerowych ani też nowych konstrukcji gramatycznych. • Istotne w naszej metodzie jest również to, że nieobecna dana (czyli odpowiednik wartości zerowej) może być dowolnie złożona, np. Adres. Taka sytuacja jest niewyrażalna w modelu i systemach relacyjnych. • Są one w stanie wyrazić sytuację, że każdy atrybut w ramach danej Adres ma wartość zerową, ale semantycznie nie jest to równoważne sytuacji, w której cała dana Adres ma wartość zerową.

  11. Nieobecne dane i funkcje agregowane • Przyjęta przez nas interpretacja nieobecnych danych jest także spójna z funkcjami agregowanymi. • Rozpatrzmy podany przez Ch.Date przykład z SQL, w którym jeżeli relacja R(A, B) posiada atrybuty A i B z wartościami zerowymi, to w generalnym przypadku zapytania: selectsum(A+B) fromR selectsum(A)+sum(B) fromR mogą zwrócić różny wynik. • W SBQL problem ten nie występuje, ponieważ syntaktyczny odpowiednik pierwszego zapytania SQL, mający postać sum(R.(A+B)) , jest błędny. • Poprawny semantyczny odpowiednik pierwszego zapytania ma w SBQL postać: sum(R.(Aasa, Basb).(a+b)) Jeżeli pewien obiekt R nie zawiera atrybutu A lub nie zawiera atrybutu B, to pod-zapytanie (Aasa, Basb) zwróci pusty wynik, wobec czego do liczenia a+b nie dojdzie • Odpowiednik drugiego zapytania ma postać: sum(R.A) + sum( R.B )

  12. Wartości zastępcze • W sytuacji, gdy zależy nam na dobrze sformatowanych strukturach, np. dla celów raportowania lub przetwarzania wyniku zapytania przez język programowania z mocną kontrolą typu, możemy zastosować metodę wartości zastępczych. • Wartość zastępcza powinna być wybrana w taki sposób, aby zastąpić ewentualny brak wartości. • Jeżeli pewnej danej nie ma, to zamiast niej programista generuje w zapytaniu wybraną wartość zastępczą, której typ jest zgodny z oczekiwanym typem nieobecnej danej. • W tym celu może posłużyć się dowolnymi już wprowadzonymi opcjami SBQL, np. funkcjami count, exists, kwantyfikatorami i innymi.

  13. Przykład z wartością zastępczą • Np. wynik podanego wyżej przykładu można byłoby w ten sposób uczynić regularnym poprzez napisanie nieco dłuższego zapytania: Prac.( deref(Nazwisko) asn, (ifexists(Zar) thenZarelse 0 ) asz, (ifexists(Zajęcie) thenZajęcieelse ”brak zajęcia”) ass)) • W tym przypadku podany wcześniej wynik uzyska regularną postać, nadającą się do wydrukowania w postaci tablicowego raportu: bag{ struct{ n(”Kowalski”), z(iZarobek1), s(iZajęcie1) }, struct{ n( „Pawlak”), z(iZarobek2), s(”brak zajęcia”) }, struct{ n( „Nowak”), z( 0 ), s(”brak zajęcia”) }, struct{ n( „Bilski”), z( 0 ), s(iZajęcie4) }, struct{ n( „Wolski”), z(iZarobek5), s(”brak zajęcia”) } } • Przy pomocy podanych konstrukcji programista może osiągnąć nie tylko wszystkie efekty, które były osiągalne poprzez zewnętrze złączenie, ale także może opanować kwestię nieregularności w danych we wszystkich innych sytuacjach.

  14. Problem z fałszywym wiązaniem • Jeżeli język zapytań nie ma kontroli typów, nieobecne obiekty w połączeniu z pełną ortogonalnością języka (nieograniczoną możliwością zagnieżdżania zapytań) prowadzą do błędu semantycznego powstającego w wyniku fałszywego wiązania. • Rozpatrzmy zapytanie: Podaj pracowników zarabiających tyle samo co Nowak: PracwhereNazwisko ”Nowak” andZar = ((PracwhereNazwisko = ”Nowak”).Zar • Interesuje nas wiązanie drugiej występującej w tym zapytaniu nazwy Zar, w sytuacji, gdy obiekt Nowaka nie posiada takiego atrybutu. • Wiązanie powinno zwrócić pusty zbiór, co spowoduje błąd wykonania. • Następny slajd pokazuje sytuację na stosie środowiskowym podczas wiązania tej nazwy, jeżeli pierwszy operator where działa na obiekcie Kowalskiego, w którym atrybut Zar występuje.

  15. Sytuacja na stosie ENVS podczas wiązania Zar • Jak widać, wbrew naszym założeniom druga nazwa Zar zostanie związana, ale do zarobku Kowalskiego, a nie Nowaka. • W efekcie, zapytanie nie wykaże błędu wykonania i zwróci referencje do wszystkich obiektów pracowników posiadających atrybut Zar. • Wynik ten jest oczywiście błędny. Kierunek przeszukiwania stosu Sekcja obiektu Nowaka (brak Zar) Sekcja obiektu Kowalskiego Nazwisko( iNazw1),... Nazwisko( iNazw2), Zar( iZar1 ),... Sekcje bazowe

  16. Jak uniknąć fałszywego wiązania (1)? • Przyczyną jest to, że w zapytaniu i w całym mechanizmie stosu nie ma informacji o tym, do którego bindera Zar ma być wiązana występująca w zapytaniu druga nazwa Zar. • Uniknięcie tego błędu zmusza do jednego z następujących rozwiązań: • Zabronienie zagnieżdżania zapytań - sprzeczne z koncepcją. • Ustalenie bardziej rygorystycznej reguły wiązania, np. po operatorze kropki wiązanie następuje wyłącznie na wierzchołku stosu. Część zapytań stanie się niewyrażalna. Podobny błąd wystąpi zresztą dla innego operatora niealgebraicznego. • Zmuszanie programistów do świadomego formułowania tego zapytania tak, aby ten błąd nie mógł wystąpić. Np. inne (poprawne w każdym przypadku) sformułowanie tego zapytania jest następujące: (PracwhereNazwisko = ”Nowak”).(Zarasx). (PracwhereNazw ”Nowak” andZar asy (x = y)) Powyższe założenie jest nieakceptowalne ze względów ergonomicznych, gdyż zmusza programistów do zbyt drobiazgowej analizy formalnej semantyki każdego zapytania.

  17. Jak uniknąć fałszywego wiązania (2)? • Określenie typów dla wszystkich obiektów i następnie, połączenie mechanizmu wiązania z przechowywaną informacją o typie. Dzięki temu można będzie wnioskować, że wprawdzie w danym obiekcie Zar nie występuje, ale w typie tego obiektu jest to opcyjne, zatem będziemy jednak wiązać Zar w tym obiekcie, co oczywiście da poprawny wynik w postaci pustego zbioru. • Skorzystanie z rozwiązania opartego na wartościach domyślnych przechowywanych w ramach klas. • Tylko dwa ostatnie rozwiązania są akceptowalne. • Radykalnym rozwiązaniem jest zastosowanie typów obiektów. • Np. można zmodyfikować funkcję nested w taki sposób, aby dla danej referencji i sprawdzała dodatkowo typ obiektu i. • Jeżeli ten typ przewidywałby opcyjną daną o nazwie n, której w danym obiekcie nie ma, funkcja zwracała dodatkowo binder n(). • W ten sposób nieobecny pod-obiekt o nazwie n byłby reprezentowany na stosie środowiskowym przez binder n().

More Related