JĘZYK ZAPYTAŃ CIĄGŁYCH

Transkrypt

JĘZYK ZAPYTAŃ CIĄGŁYCH
POLITECHNIKA ŚLĄSKA
INSTYTUT INFORMATYKI
Labolatorium ZBiHD
JĘZYK ZAPYTAŃ CIĄGŁYCH
Marcin Gorawski
Aleksander Chrószcz
Gliwice 2007
Spis treści:
1
WSTĘP
3
2
WPROWADZENIE
4
3
4
5
2.1
ZALETY PRZETWARZANIA STRUMIENIOWEGO
4
2.2
JĘZYK ZAPYTAŃ
4
2.3
POJĘCIA PODSTAWOWE
5
2.4
MODELE PRZETWARZANIA STRUMIENIOWEGO
7
2.4.1
Strumienie danych z interpunkcją
2.4.2
Model przetwarzania strumień/relacja relacja/strumień
11
2.4.3
Algebra operatorów danych temporalnych
13
SYSTEM STREAM APAS V2.0
7
13
3.1
ARCHITEKTURA SYSTEMU PRZETWARZANIA STRUMIENIOWEGO
13
3.2
ARCHITEKTURA WĘZŁA PRZETWARZAJĄCEGO
15
3.3
STRUMIENIE DANYCH
16
3.4
OPERATORY
16
3.4.1
Filtr
17
3.4.2
Mapa
17
3.4.3
Produkt kartezjański
17
3.4.4
Okno czasowe
17
3.4.5
Unia
18
3.5
OPERACJA REORGANIZACJI
18
3.6
KOLEKCJE KROTEK
19
3.7
UPORZĄDKOWANIE KROTEK W STRUMIENIACH
20
JĘZYK ZAPYTAŃ
21
4.1
DRZEWA ATRYBUTÓW
21
4.2
SKŁADNIA ZAPYTANIA
23
4.3
PRZYKŁADOWE ZAPYTANIE
24
LITERATURA
26
1 Wstęp
Rozszerzenie definicji danych jako strumieni pozwala skorzystać z potokowości
przetwarzania, która zwiększa skalowalność rozwiązań. Elementem wyróżniającym tą klasę
systemów jest polityka zarządzania danymi historycznymi. Ograniczenie potrzeby archiwizacji jest
koniecznością w przypadku systemów zasilanych dużą liczbą danych. Systemy przetwarzania
strumieniowego (ang. Stream Processing System) (w skrócie: systemy strumieniowe) służą
przetwarzaniu strumieni danych a nie ich gromadzeniu, powyższa własność sprzyja ich
zastosowaniu w analityce i systemach wspierających podejmowanie decyzji(DSS). Dodatkowo
uzyskiwane wyniki odzwierciedlają bieżący stan systemu, co jest oczekiwane w zastosowaniach
takich jak: nadzorowanie ruchu ulicznego, monitorowanie notowań giełdowych. Przyjęcie
koncepcji przetwarzania strumieniowego wiąże się z większą złożonością procesu uruchamiania
zapytania, która może wymagać zasilenia danymi historycznymi, słownikami oraz mapami.
Ponadto w trakcie działania zapytania należy monitorować węzły przetwarzające, aby w przypadku
awarii poprawnie wyłączyć sieć przetwarzania.
Przebieg ćwiczenia jest podzielony na następujące etapy:
1. zapoznanie się z podstawami teoretycznymi przetwarzania strumieniowego,
2. zapoznanie się z aplikacją strumieniowej bazy danych,
3. wykonanie przykładowych zapytań.
Sprawozdanie powinno zawierać:
1. wstęp krótko definiujący tematykę zajęć,
2. opis przebiegu laboratorium,
3. propozycja rozwiązania problemu przedstawionego przez prowadzącego ćwiczenia.
2 Wprowadzenie
2.1 Zalety przetwarzania strumieniowego
Systemy przetwarzania strumieniowego znacząco różnią się od tradycyjnych systemów
bazodanowych, w których dane są wpierw zapisywane, następnie wyliczane są indeksy, na koniec
wyznaczane odpowiedzi na zgromadzonych zasobach. W przed-stawionej aplikacji źródła generują
nieograniczonych rozmiarów strumienie danych, które są na bieżąco przetwarzane przy użyciu
długookresowych zapytań. Systemy przetwarzania strumieni wyróżniają następujące cechy [2]:
ciągłe przetwarzania – w systemach DBMS obowiązkiem klienta jest zadawanie zapytań
na zgromadzonych danych („czy stopa zwrotu osiągnęła zadany pułap„). W systemie
strumieniowym użytkownik uruchamia długookresowe zapytanie („powiadom mnie, gdy stopa
zwrotu osiągnie zadany pułap”).
„wypychanie” danych – źródła danych oraz węzły przetwarzające strumienie przekazują
krotki kolejnym obiektom w systemie. W DBMS klienci aktywnie wywołują zapytania w celu
aktualizacji wyników, podczas gdy w systemie strumieniowym klient oczekuje na nie pasywnie.
krótki czas latencji – wiele systemów strumieniowych monitoruje zachodzące zjawiska
przy rygorze krótkiego czasu odpowiedzi. Przykładowo dla systemu nadzorującego ruch uliczny
ważniejsza jest bieżąca informacja o stanie drożności ulic niż wystąpienie korków kilka godzin
wcześniej.
potokowość – przetwarzanie danych bazuje na nieblokowalności, własność ta pozwala na
wydajną współbieżną pracę węzłów sieci przetwarzania.
skalowalność – każdy węzeł stanowi samodzielną jednostkę co ułatwia umieszczenie
sieci przetwarzającej w środowisku rozproszonym.
wysoka przepustowość – system strumieniowy nie gromadzi danych tylko je przetwarza
dzięki czemu ogranicza się wąskie gardło systemów DBMS, którym jest potrzeba zapisu
wszystkich danych na dysk.
2.2 Język zapytań
Obecnie brak standardu języka zapytań strumieniowych. Może się wydawać, że
zdefiniowanie języka zapytań ciągłych dla strumieni danych nie stanowi problemu, ponieważ
algebra relacji systemów strumieniowych nie odbiega znacząco od algebry relacji tradycyjnych baz
danych. Idąc dalej wystarczyłoby wziąć język SQL, zastąpić relacje na tabelach relacjami na
strumieniach, utworzyć nowy procesor zapytań strumieniowych i zmienić aktywny model obsługi
wyników na pasywny. Dla prostych zapytań podejście takie jest wystarczające. Jeżeli jednak
planujemy użycie agregatów, zapytań złożonych, okien czasowych oraz dostępu do danych
tabelarycznych rozwiązanie takie zawodzi. Rozważmy poniższe zapytanie:
Select P.price
From Items [Rows 5] as I, PriceTable as P
Where I.itemID = P.itemID
Items reprezentuje strumień ze sprzedanymi przedmiotami, PriceTable jest tabelą
zawierającą ceny produktów oraz [Rows 5] definiuje okno składające się z 5-ciu ostatnich wpisów.
Nawet tak proste zapytanie nie posiada jednoznacznej interpretacji. Dla powyższego przykładu
można zadać pytanie czy otrzymany wynik jest relacją czy strumieniem. Co się stanie, jeżeli cena
ostatnio sprzedanego produktu ulegnie zmianie, podczas gdy obiekt ten nadal będzie znajdował się
w 5-cio elementowym oknie?
Aby odpowiedzieć na pytanie jakie dane otrzymamy w wyniku realizacji powyższego
zapytania należy uściślić model przetwarzania strumieniowego.
2.3 Pojęcia podstawowe
Krotka reprezentuje pojedynczą porcję danych przesyłaną w strumieniu.
Strumień danych w ogólnym ujęciu to medium które przesyła nieskończoną kolekcję
krotek wśród których możemy wyróżnić krotki z danymi oraz krotki specjalne (systemowe,
interpunkcji). Należy zwrócić uwagę na to, że strumień przesyła krotki tylko raz. Zatem, jeżeli
operator strumieniowy musi odwołać się do krotek nadesłanych wcześniej, musi je przechowywać
we wewnętrznych strukturach.
Tradycyjna baza danych udostępnia między innymi operatory: filtr( σ ), mapa( µ ),
łączenie( >< ),agregacja( α ), grupowanie, unia(
U
), różnica.
Operatory możemy podzielić na dwie grupy:
1. bezstanowe – operator bezstanowy wylicza wynik w oparciu o krotkę wejściową,
bez potrzeby korzystania z dodatkowych danych przechowywanych wewnątrz
operatora. Typowymi operatorami bezstanowymi są: filtracja i mapowanie. Do
odfiltrowania czyli usunięcia krotki ze strumienia wystarczy aby wartość
predykatu wynosiła fałsz, przy czym jest on zdefiniowany tylko na atrybutach
krotki wejściowej.
2. stanowe – operator stanowy wymaga przechowywania dodatkowych danych.
Dane te mogą być aktualizowane wraz z nadejściem kolejnych krotek na wejście.
Zaliczamy tutaj np. operator różnicy. Operacja różnicy usuwa ze strumienia
lewego krotki które pojawiły się w strumieniu prawym. Realizacja takiego
operatora sprowadza się do przechowywania krotek strumienia prawego w
wewnętrznej strukturze operatora, po czym nadejście krotki strumienia lewego
wyzwala sprawdzenie czy nie istnieje w wewnętrznej kolekcji operatora; jeżeli nie
to zostaje przekazana na wyjście.
Większość operatorów tradycyjnej bazy danych nie nadaje się do utworzenia systemu
przetwarzania strumieniowego. Wyróżniamy dwie cechy które ograniczają zastosowanie tych
operatorów w systemach strumieniowych:
1. blokowalność operatora – operator musi odczytać pełny zbiór danych
wejściowych zanim będzie mógł wygenerować wynik (np. operacja grupowania,
sortowania). Taka własność operatora nie pozwala na zastosowanie jego w
przetwarzaniu strumieniowym, ponieważ strumień jest kolekcją nieskończoną.
Użycie takiego operatora skutkowałoby zablokowaniem pracy do momentu
otrzymania informacji o zamknięciu strumienia, po czym możliwe byłoby
przetworzenie zgromadzonych danych. Warto tutaj zauważyć, że jeżeli znamy
charakter danych strumieniowych pojęcie blokowalności operatorów jest bardziej
złożonym zagadnieniem. Przyjmijmy, że chcemy pogrupować dane ze strumienia
wejściowego względem atrybutu A oraz wiemy, że ten strumień przekazuje krotki
w porządku rosnącym względem atrybutu A. Operator grupowania który w
ogólnym zastosowaniu jest blokowany w tym przypadku jest nie blokowany,
ponieważ na podstawie napływających danych potrafimy zidentyfikować ostatnią
krotkę podgrupy. Uogólniając tradycyjny operator grupowania można zastosować
do przetwarzania strumieni monotonicznie nie malejących względem atrybutów
grupowania.
2. nieograniczony stan operatora – każdy operator w rzeczywistym systemie
dysponuje ograniczonym rozmiarem zasobów. Operatory strumieniowe
przetwarzają nieskończoną kolekcję krotek, zatem jeżeli do wyliczenia wyniku
należy przechowywać otrzymane wcześniej dane wejściowe, w pewnym
momencie praca operatora zostanie przerwana z powodu braku wolnych zasobów.
Przykładem jest operator eliminacji duplikatów, jeżeli dana krotka pojawia się
pierwszy raz na wejściu zostaje ona zapisana do struktury wewnętrznej operatora
oraz przekazana na wyjście. Ponowne otrzymanie identycznej krotki skutkuje jej
odfiltrowaniem.
Samo zdefiniowanie zbioru operatorów nie blokowanych nie wystarcza do zbudowania
procesora strumieni. Operatory te musi również cechować ograniczony stan operatora co
gwarantuje, że praca systemu nie zostanie wstrzymana na skutek braku wolnych zasobów. Obecnie
istnieje kilka propozycji w jaki sposób zaadaptować operatory tradycyjnych baz danych do
przetwarzania danych strumieniowych, co zostanie przedstawione w kolejnych paragrafach.
Przystępując do budowy operatorów strumieniowych należy odpowiedzieć na pytanie jak
zamierzamy zrealizować trzy typy niezmienników:
• niezmiennik przejścia (pass invariants) – definiuje kiedy operator dysponuje
kompletem danych potrzebnym do wyliczenia wyniku; niezmiennik ten informuje
kiedy operator może wygenerować wynik (tzn. kiedy jest odblokowany).
• niezmiennik stanu (keep invariants) – definiuje obsługę elementów składających
się na stan operatora; niezmiennik ten zabezpiecza przed przepełnieniem struktur
wewnętrznych operatora.
• niezmiennik propagacji (propagation invariants) – definiuje sposób obsługi krotek
specjalnych (systemowych, interpunkcji), mechanizm generacji nowych krotek
specjalnych oraz warunki przy jakich następuje ich propagacja do strumieni
wyjściowych.
2.4 Modele przetwarzania strumieniowego
2.4.1 Strumienie danych z interpunkcją
Interpunkcja reprezentowana jest jako krotka o specjalnym typie. Interpunkcja stabilizuje
oraz zaznacza koniec pewnego fragmentu strumienia. Stabilizacja fragmentu strumienia
wejściowego służy poinformowaniu operatora o tym, że kolejne krotki które napłyną na wejście
nie mają wpływu na bieżący wynik obliczeń. Wyobraźmy sobie że chcemy posortować imiona w
strumieniu wejściowym w porządku alfabetycznym, bez mechanizmu interpunkcji musielibyśmy
zaczekać do momentu, gdy otrzymamy pełen komplet danych wejściowych. Wystarczy
wprowadzić krotkę interpunkcji która powiadomi o tym, że przekazano wszystkie imiona od A-D.
Wówczas operator może uporządkować dane oraz przesłać je na wyjście, ponieważ wiemy że
kolejne krotki wejściowe nie wpłyną już na ten fragment wyniku zapytania (tzn. wygenerowane
krotki wyjściowe będą stabilne). Interpunkcja pozwala nam uczynić operatory nie monotoniczne
co najmniej częściowo monotonicznymi, w wyniku tego możliwe jest ich zastosowanie w
przetwarzaniu strumieniowym.
Przyjmijmy następującą definicję krotki interpunkcji. Krotka interpunkcji definiuje zakres
wartości wszystkich atrybutów wchodzących w skład krotki danych. Możemy zdefiniować
następujące typy zakresu wartości atrybutów:
wildcard (*) – oznacza pełny zakres dziedziny atrybutu,
constant – precyzuje pojedynczą wartość atrybutu,
range – definiuje zakres wartości atrybutu,
list – definiuje listę wartości atrybutu.
Korzystając z notacji XML poniżej zamieszczono kilka przykładów krotek interpunkcji:
<!--przesłano wszystkie pomiary temperatur do 75 stopni C dla godziny 8 -->
<punct:SENSOR>
<ID> * </ID>
<HOUR> 8 </HOUR>
<MINUTE> * </MINUTE>
<TEMP> [,75) </TEMP>
</punct:SENSOR>
<!--przesłano wszystkie pomiary temperatur dla sensorów o numerze identyfikacyjnym: 1,5,6 -->
<punct:SENSOR>
<ID> {1,5,6} </ID>
<HOUR> * </HOUR>
<MINUTE> * </MINUTE>
<TEMP> * </TEMP>
</punct:SENSOR>
Akcje wywoływane po odbiorze interpunkcji:
- operator identyfikuje które dane może przekazać na wyjście
- redukowany jest stan operatora
- przekazywane są na wyjście krotki interpunkcji
Mówimy że strumień z interpunkcją jest poprawny gramatycznie jeżeli krotka
interpunkcji pojawia się w strumieniu wtedy, gdy wszystkie krotki opisane przez tą krotkę
interpunkcji zostały już przesłane.
Dla uproszczenia analizy zdefiniujmy funkcję match która zwróci wartość true, gdy
krotka danych jest opisana przez wskazaną krotkę interpunkcji.
Przyjmijmy że strumień danych będziemy oznaczali [| |]. Pojedyncza porcja danych
przesyłana w strumieniu z interpunkcją to lista krotek oznaczana [ ]. Aby rozróżnić typ krotki
stosujemy literę P jako prefix krotek interpunkcji; oto przykład strumienia danych: [|[1,5], [3],
[P(0,4)], [5,6,7],…|]. Przeanalizujemy teraz działanie kilku operatorów zbudowanych na
strumieniach z interpunkcją.
2.4.1.1
Operator z pojedynczym strumieniem wejściowym
Idee działania takiego operatora można przedstawić jako wywołanie kolejno poniższych
funkcji dla każdej krotki wejściowej:
step: [input] state ([output], state)
pass: [inputp] state [output]
prop: [inputp] state [outputp]
keep: [inputp] state [state]
gdzie:
input – wejściowe krotki danych,
output – wyjściowe krotki danych,
inputp – wejściowe krotki interpunkcji,
outputp – wyjściowe krotki interpunkcji,
state – struktura w której operator zapisuje stan.
Opis funkcji:
step - definiuje jak zachowuje się operator po nadejściu nowej krotki danych (tzn.
aktualizacje stanu operatora oraz jakie krotki przekazywane są na wyjście).
pass - definiuje które krotki danych mogą zostać przekazane na wyjście po otrzymaniu
nowej krotki interpunkcji.
prop - definiuje które krotki interpunkcji zostają przesłane na wyjście po nadejściu nowej
krotki interpunkcji.
keep - definiuje które dane wewnątrz operatora mogą zostać usunięte.
Jeżeli dana krotka reprezentuje interpunkcję wówczas na wejście input podawana jest
krotka pusta, analogicznie gdy na wejściu pojawi się krotka danych wtedy na inputp podawana jest
krotka pusta.
Przykładem operatora jednowejściowego jest eliminacja duplikatów. Dla powyższego
szkieletu otrzymujemy następujące definicje funkcji:
step – sprawdza czy krotka wejściowa nie jest duplikatem (przegląda wewnętrzną listę
krotek historii), jeżeli jest unikalna przekazujemy ją na wyjście oraz dodajemy do
listy krotek historii.
pass – operator eliminacji duplikatów jest nie blokujący dlatego brak potrzeby
definiowania tej funkcji.
prop – przekazuje na wyjście otrzymaną na wejściu krotkę interpunkcji.
keep – usuwa z listy (do której wstawiane są unikalne krotki wejściowe) te elementy,
które są pokrywane krotkę interpunkcji na wejściu.
Prześledzimy działanie operatora eliminacji duplikatów dla strumienia: [| [1,5], [3],
[P(0,4)], [5,6,7],…|].
funkcja We
stan
wy
nowy stan
step
[1,5]
[]
[1,5]
[1,5]
prop
[]
[1,5]
[]
keep
[]
[1,5]
step
[3]
[1,5]
prop
[]
[1,5,3] []
keep
[]
[1,5,3]
[1,5]
[3]
[1,5,3]
[1,5,3]
2.4.1.2
step
[]
[1,5,3] []
prop
[P(0,4)] [1,5,3] [P(0,4)]
keep
[P(0,4)] [1,5,3]
step
[5,6,7]
[5]
prop
[]
[5,6,7] []
keep
[]
[5,6,7]
[1,5,3]
[5]
[6,7]
[5,6,7]
[5,6,7]
Operator z dwoma strumieniami wejściowymi
W przypadku takiego operatora dysponujemy oddzielną grupą funkcji dla strumienia
wejścia lewego oraz prawego:
stepL
stepR
passL
passR
propL popr.
keepL keepR
Przykładem operatora dwuargumentowego jest różnica strumieni, jego zadaniem jest
odfiltrowanie ze strumienia lewego krotki występujące w strumieniu prawym. W operatorze tym
definiujemy dwie listy przechowujące oddzielnie interpunkcję dla strumienia lewego oraz
prawego. Krotki danych z lewego strumienia mogą zostać przekazane na wyjście jeżeli są pokryte
przez interpunkcję prawego strumienia i nie występują w liście krotek danych prawego strumienia.
Przekazanie interpunkcji na wyjście wymaga uwzględnienia obu strumieni, tzn. na wyjście
przekazywane są tylko te krotki interpunkcji które opisują jednocześnie oba strumienie wejściowe.
Funkcji keepR redukuje listę krotek historii dla strumienia prawego w oparciu o krotki interpunkcji
przekazane na wejście lewe (zachowywane są tylko te dane które nie są opisane przez interpunkcję
strumienia przeciwnego). Jak można zauważyć operator ten nie definiuje funkcji stepL oraz stepR,
ponieważ dopiero nadejście krotek interpunkcji pozwala uruchomić proces wyznaczania wyniku.
2.4.1.3
Podsumowanie strumieni z interpunkcją
Istotną zaletą strumieni z interpunkcją jest to, że nie nakładają warunków
wprowadzających uporządkowanie krotek wewnątrz strumieni. Przedstawiona metoda
przetwarzania strumieni danych wiąże się z bardziej złożony projektem sieci przetwarzania
strumieniowego, ponieważ należy zapewnić poprawną propagację krotek interpunkcji. Zadanie to
nie zawsze jest banalne, wyobraźmy sobie operator który dokonuje konwersji liczby na tekst.
Konwersji wymagają również krotki interpunkcji które pojawiają się na wejściu, prosta zamiana z
P(11,33) na P(„11”,”33”) jest błędna, ponieważ przedział nazw od „11” do „33” przy
uwzględnieniu porządku alfabetycznego obejmuje większy zbiór dozwolonych wartości niż tylko
liczbowe. Pozostaje także ustalić z jaką częstością generować krotki interpunkcji, tak aby system
działał płynnie z drugiej strony wzrost kosztu pracy sytemu wynikający z takich krotek był
utrzymany na niskim poziomie.
2.4.2 Model przetwarzania strumień/relacja relacja/strumień
Podejście stream-to-relation-to-stream wychodzi z założenia, że operatory tradycyjnych
baz danych mogą przetwarzać strumienie jeżeli zdefiniujemy następujące funkcje konwersji:
• konwersja strumień-tabela
• konwersja tabela-strumień
Nadejście nowej krotki w takim modelu przetwarzania wyzwala aktualizację tabeli
budowanej na wskazanym strumieniu wejściowym, po czym następuje wyliczenie zapytania tak
jakby miało to miejsce w tradycyjnej bazie danych. Otrzymana tabela rekordów wynikowych jest
w dalszym etapie konwertowana do postaci strumienia wyjściowego. Taka koncepcja
przetwarzania danych strumieniowych sprowadza problem do wprowadzenia dwóch nowych
operatorów.
2.4.2.1
Konwersja strumień-tabela
Naturalną funkcją konwertującą dane strumieniowe do postaci tabeli jest okno czasowe.
Przyjmijmy, że każda krotka posiada znacznik czasu τ , zatem można ją opisać jako parę ( s, τ )
gdzie: s - wartości atrybutów, τ - znacznik czasu. Okno czasowe jest to funkcja która definiuje
czas życia elementu tabeli na postawie znacznika czasu krotki. Nadejście nowej krotki na wejście
skutkuje aktualizacją bieżącego czasu operatora zgodnie ze znacznikiem czasu tej krotki.
Wyróżniamy następujące okna czasowe:
przesuwne (sliding window) – parametrem okna jest rozmiar T w jednostkach czasu.
Każda nowa krotka wejściowa wstawiana jest do tabeli, następnie
aktualizowany jest bieżący czas operatora, po czym tabela jest oczyszczana
z krotek których znaczniki czasu wychodzą poza zakres okna. Okno
przesuwne pozwala zgrupować krotki z przeciągu ostatnich T jednostek
czasu. Działanie tego okna można wyrazić:
R(τ ) = {s | ( s,τ ' ) ∈ S ∧ (τ ' ≤ τ ) ∧ (τ ' ≥ max(τ − T ,0))}
gdzie:
S – strumień danych
τ - bieżący czas operatora
T – rozmiar okna
sekwencyjne (fixed window) – parametrem okna jest rozmiar T w jednostkach czasu,
interwał tego okna definiujemy następująco:
znacznik początku: i*T
znacznik końca: (i+1)*T
Przy jego użyciu możemy grupować krotki np. w przedziały godzinne przy
czym początek każdego okna przypada na pełną godzinę zegarową.
2.4.2.2
Konwersja tabela-strumień
Wyróżniamy kilka konwersji tabeli wynikowej na strumień. W najprostszym przypadku
wstawiamy do strumienia wszystkie krotki tabeli wynikowej. Nie jest to najrozsądniejsze
rozwiązanie. Wyobraźmy sobie, że realizujemy operator łączenia strumieni. W wyniku nadejścia
nowej krotki aktualizowane są tabele wejściowe operatora, następnie generowany wynik zgodnie z
predykatem łączenia. Należy zauważyć, że utworzona tabela wynikowa zawiera wszystkie
poprawne połączenia krotek zbudowane na tabelach źródłowych, a nie tylko wynik połączenia
nowej krotki z tabelą krotek strumienia przeciwnego. Wstawienie krotek takiej tabeli wynikowej
do strumienia wyjściowego skutkuje wprowadzeniem do systemu ogromnej liczby duplikatów.
Dlatego udostępniono bardziej złożone operatory konwersji tabeli wynikowej na strumień:
Istream (insert stream) – do strumienia wyjściowego wstawiane są tylko krotki nowe
względem poprzedniej tabeli wynikowej.
Istream(R ) = U ((R(τ ) − R(τ − 1))× {r})
τ ≥0
Dstream (delete stream) – do strumienia wyjściowego wstawiane są elementy których
zostały usunięte z poprzedniej tabeli wynikowej.
Istream(R ) = U ((R(τ − 1) − R(τ ))× {r})
τ >0
Rstream (relation stream) – do strumienia wyjściowego wstawiane są wszystkie elementy
tabeli wynikowej.
Rstream(R ) = U (R(τ )× {r})
τ ≥0
2.4.2.3
Podsumowanie modelu przetwarzania strumień/relacja
relacja/strumień
Model takiego przetwarzania strumieni w odniesieniu do przetwarzania strumieni z
interpunkcją jest wolny od potrzeby definiowania mechanizmu generowania krotek interpunkcji.
Model ten z drugiej strony nakłada warunek uporządkowania krotek strumieni chronologicznie
względem znaczników czasu. Jeżeli operator ma kilka strumieni wejściowych należy krotki tych
strumieni wejściowych wstępnie uporządkować. Słabą stroną takiego przetwarzania strumieni jest
ograniczenie sterowania stanem operatora do funkcji okien czasowych. Drugim słabym elementem
takiego modelu przetwarzania jest przewaga operatorów typu strumień-relacja-strumień które są
wolniejsze od operatorów strumień-strumień. Główną zaletą takiego podejścia do przetwarzania
strumieni jest prostota tworzenia zapytań. Do nauczenia się obsługi takiej platformy przetwarzania
strumieni wystarczy zaznajomienie się z funkcjami konwersji strumień tabela, ponieważ
działanie reszty operatorów jest identyczne jak w tradycyjnych bazach danych.
2.4.3 Algebra operatorów danych temporalnych
Chęć utworzenia modelu przetwarzania w którym wszystkie operatory byłyby typu
strumień-strumień poskutkowało zdefiniowaniem algebry operatorów dla danych temporalnych.
Przystępując do budowy tego modelu przetwarzania zadecydowano, aby każda krotka
indywidualnie definiowała czas aktywności poprzez znaczniki początku i końca czasu życia. Z
chwilą kiedy istnienie krotki jest umiejscowione w czasie, definicja operatorów staje się o wiele
prostsza. Ustalenie które krotki tworzą stan operatora sprowadza się do zweryfikowania ich czasu
życia z bieżącym czasem operatora. Warto tutaj zwrócić uwagę na inną konstrukcję operatora
łączenia. Aby połączyć krotki dwóch strumieni nie tylko musi zachodzić predykat łączenia ale
również łączone krotki muszą mieć wspólny okres czasu życia. Utworzona krotka wynikowa
składa się z atrybutów krotek łączonych, a jej czas życia to część wspólna czasów życia krotek
łączonych. Precyzyjniejszy opis implementacji tej algebry zamieszczono w następnym rozdziale.
3 System Stream APAS v2.0
3.1 Architektura systemu przetwarzania strumieniowego
poglądowy
Na rys.1 zamieszczono
strumieniowego.
schemat
Interfejs
użytkownika
zbudowanego
przetwarzania
N adzorca zapytań
S ieci
przetwa rzania
R ejestracja strum ieni
systemu
Zarządca warstwy
zasilania
N asłuchiwanie zgłoszeń
źródeł
K om pilator
zapytań
K atalog zasobów
K om unikacja ze źródłam i
Rys. 1. Architektura systemu przetwarzania strumieniowego
Fig. 1. The architecture of the stream processing system
Poniżej przedstawiono opis ważniejszych elementów składowych systemu.
Zarządca warstwy zasilania – moduł ten aktualizuje informacje o meta-schemacie strumieni
w ramach katalogu zasobów oraz zasila danymi uruchomione strumieniowe sieci przetwarzania.
Aby podłączyć do systemu nowe źródło danych należy wpierw zarejestrować nazwę, pod którą
dany zasób będzie dostępny. W ramach rejestracji nie podajemy definicji meta-schematu
strumienia, dostarcza go źródło danych. Po dodaniu nowego strumienia jest on widoczny w
katalogu zasobów jako nie podłączony oraz z pustym meta-schematem. Jeżeli użytkownik zbuduje
zapytanie zasilane takim strumieniem, kompilator zgłosi błąd informujący o braku atrybutów, do
których zdefiniowano odwołania.
Procedura przyjęcia zgłoszenia źródła danych:
•
pobranie adresu zgłaszanego źródła,
•
utworzenie wątku obsługującego wskazany kanał komunikacji,
•
oczekiwanie na krotkę definiującą meta-schemat strumienia,
• odbiór krotek z danymi.
W trakcie pracy strumienia możliwa jest zmiana meta-schematu. W tym celu źródło przesyła
krotkę systemową z nową definicją. Zarządca warstwy zasilania aktualizuje wtedy zawartość
katalogu zasobów oraz przekazuje tą krotkę do strumieni wewnątrz systemu. Dzięki temu
uruchomione zapytania zasilane tym źródłem informowane są o aktualizacji.
Katalog zasobów – repozytorium dostępnych w systemie strumieni.
Nadzorca zapytań – zapytanie strumieniowe to długookresowy proces, dlatego rolą nadzorcy
zapytań jest nie tylko kontrolowanie przebiegu kompilacji, ale również nadzór uruchomionej sieci
przetwarzania. Aby uprościć zarządzanie uruchomionymi sieciami przetwarzania przyjęto, że
zapytania są rejestrowane pod wybraną przez użytkownika nazwą. Dzięki temu w chwili
wystąpienia awarii łatwo odnaleźć jej przyczynę na podstawie logów historii gromadzonych dla
każdego zapytania oddzielnie. Przetwarzanie strumieniowe jest procesem wielowątkowym, dlatego
moduł ten implementuje procedurę bezpiecznego wyłączenia zapytania, która gwarantuje
zwolnienie wszystkich zasobów systemowych zajętych przez daną sieć przetwarzania. Kolejnym
zadaniem nadzorcy zapytań jest obsługa komunikatów specjalnych generowanych przez sieć
przetwarzania.
Sygnalizują one:
•
wykrycie zmiany meta-schematu jednego z strumieni źródłowych,
•
usunięcie strumienia źródłowego z katalogu strumieni,
• odbiór wyjątku w trakcie pracy węzła przetwarzającego.
Jeżeli zapytanie nie definiuje metody obsługi komunikatu, nadzorca przystępuje do wyłączenia
sieci przetwarzania.
Kompilator zapytania – kompiluje zapytanie do postaci sieci przetwarzania strumieniowego.
Potrzebne informacje o strukturach strumieni pobiera z katalogu zasobów, z kolei wykryte błędy w
zapytaniu kieruje do nadzorcy zapytania.
Sieć przetwarzania – przy użyciu operatorów fizycznych implementuje operacje logiczne
zdefiniowane poprzez zapytanie w postaci tekstowej. Sieć przetwarzania to węzły przetwarzające
połączone strumieniami danych. Węzeł przetwarzający jest platformą na której uruchamiane są
operatory fizyczne. Architektura taka w przejrzysty sposób rozdziela
funkcjonalność
wykorzystywaną przez większość operatów fizycznych (taką jak porządkowanie krotek strumieni
wejściowych, obsługa komunikatów błędów) od konkretnej realizacji operatora fizycznego.
Ponieważ przetwarzanie strumieniowe jest nie blokowalane każdy z węzłów przetwarzających
pracuje w ramach oddzielnego wątku. Przetwarzanie strumieniowe jest nie blokowalne tzn. dany
operator nie przetwarza całego zbioru danych wejściowych zanim przekaże wyliczone wyniki do
kolejnego operatora w planie produkcji. Proces przetwarzania strumieniowego dzięki zastosowaniu
okien czasowych jest nie blokowalny czyli dla każdej krotki wejściowej operator potrafi
natychmiast wyliczyć wynik.
3.2 Architektura węzła przetwarzającego
Aby strumienie wewnątrz pojedynczego zapytania działały wydajnie, każdy z nich transportuje
minimalny zbiór atrybutów konicznych do ukończenia przetwarzania zapytania.
W ę z e ł P r z e t w a r z a ją c y
S y n c h r o n iz a c j a
s t r u m ie n i
W y lic z a n y
o p e ra to r
a lg e b r y
µ
k o le k c j e g r o m a d z ą c e k r o t k i
Rys. 2. Przepływ krotek w węźle przetwarzającym
Fig. 2. Tuples data flow in the processing node
Cel ten jest osiągany poprzez wprowadzenie operacji mapującej na wyjściu każdego węzła
przetwarzającego.
Na rys. 2. przedstawiono przepływ krotek w trakcie wyliczania zapytania. Scenariusz działania
jest następujący:
1. Uporządkowanie leksykograficzne krotek jeżeli operator posiada kilka strumieni
wejściowych,
2. Reorganizacja kolekcji w oparciu o znacznik czasu krotki przekazanej do
przetworzenia,
3. Wstawienie krotki do kolekcji,
4. Realizacja operacji algebry,
5. Wyznaczenie krotki wynikowej (wstawienie do strumienia wynikowego krotki z
zredukowaną liczbą atrybutów).
Jeżeli dana kolekcja zasila dodatkowo indeks, zamiany zachodzące w wyniku wstawienia
krotki i reorganizacji struktury zgłaszane są przy użyciu wydarzeń: insert, update, delete.
3.3 Strumienie danych
Niech I := {[t s , t e ) ∈ T × T | t s ≤ t e } oznacza zbiór przedziałów czasowych włącznie z punktami
czasowymi, gdzie T jest dziedziną czasu, wprowadzamy również Ω , która oznacza przestrzeń
dostępnych atrybutów.
Definicja 1.
(
)
Strumień opisuje para symboli S = M ,≤ ts ,te gdzie:
M - nieskończony strumień krotek (type, e, [t s , t e ) ) gdzie: type - typ krotki, e – dane
transportowane przez krotkę [t s , t e ) ∈ I
≤ t s ,te - uporządkowanie leksykograficzne elementów strumienia M (wpierw po ts potem
po te).
W systemie rozróżniamy kilka typów krotek (tab.1), przez co możliwe jest zarządzanie siecią
przetwarzania przy użyciu strumieni źródłowych.
Tab .1.
Typy krotek w systemie
Typ
Opis
HEADER
definiuje metaschemat krotek INSERTION
REMOVE
Informuje o usunięciu strumienia z systemu
STOP
wstrzymuje działanie operatorów
INSERTION
służy transmisji wartości atrybutów
BOUNDARY
znacznik upływu czasu
3.4 Operatory
Logika operatorów algebry bazuje na architekturze zaproponowanej w [3]. Aktualnie
system wspiera operatory: filtr( σ ), mapa( µ ), łączenie( >< ), okno czasowe( ω ), unia(
U
),
agregacja( α ). Ponieważ w dalszej części podrozdziału przedstawione zostaną operatory
zdefiniowane tylko na krotkach typu INSERTION, pominięty zostanie element type definicji
krotki.
3.4.1 Filtr
Niech P jest zbiorem predykatów filtracji takich, że p ∈ P p : (Ω × T ) → {true, false} .
Filtr σ : S × P → S zwraca krotki, dla których predykat ma wartość pozytywną. W systemie
strumieniowym operator filtracji definiujemy:
σ p (S ) := {(e, t ) ∈ S | p (e, t )}
3.4.2 Mapa
Niech Fmap jest zbiorem wszystkich funkcji mapujących takich, że f ∈ Fmap f : Ω → Ω ;
warto zauważyć, że f może być funkcją n-argumentową, ponieważ Ω jest uniwersum atrybutów
krotki. Operator mapy µ f : S × Fmap → S dla systemu strumieniowego definiujemy:
µ f (S ) := {(e, t ) | (eˆ, t ) ∈ S | e = f (eˆ )}
Należy zauważyć, że ogólność definicji operatora mapy pozwala na realizowanie przy
jego użyciu również operacji projekcji atrybutów.
3.4.3 Produkt kartezjański
Produkt kartezjański × : S × S → S dla systemu strumieniowego definiujemy:
× (S1 , S 2 ) := {(o (e1 , e2 ), t ) | (∃(e1 , t1 ) ∈ S1 ∧ ∃(e2 , t 2 ) ∈ S 2 ∧ int er sec t (t1 , t 2 )), t = overlap(t1 , t 2 )}
Operator łączy ze sobą tylko te krotki, których czas życia nachodzi na siebie. Wynikowa
krotka otrzymuje czas równy części wspólnej czasów życia łączonych krotek.
3.4.4 Okno czasowe
Utworzona logika modeluje okna czasowe poprzez przypisanie każdej krotce czasu
życia[3]. Niech w∈ T , operator okna czasowego ω definiujemy wtedy: ω w : S × T → S . Pozwala
to utworzyć między innymi okna:
infinity – czas życia krotki ustawiany jest na nieskończoność; krotka (e,[t s , t e )) jest
przetwarzana do postaci (e,[t s , ∞)) .
range – tworzy okno przesuwające się; krotka (e,[t s , t e )) jest przetwarzana do postaci
(e,[t s , t s + w)) , gdzie:
w – czas życia krotki.
fixed – dziedzina czasu zostaje podzielona w na sekcje o stałym rozmiarze w. Sekcja
rozpoczyna się w chwili i * w gdzie i ∈ N 0 a kończy (i + 1) * w . Dla każdej
krotki (e,[t s , t e )) wyznaczany jest nowy znacznik t e = i * w będący liczbą
najbliższą ts spełniającą warunek t s < t e .
Jeżeli nie znamy czasu życia krotki źródłowej należy go ustawić na zero,
w przeciwieństwie do zaproponowanej w [3] nieskończoności. Założenie to nie zmienia
funkcjonalności, ponieważ dysponujemy operatorami okien czasowych, zabezpiecza z kolei przed
nieumyślną budową okien o nieskończonym rozmiarze.
3.4.5 Unia
Operator unii
∪ + : S1 × S 2 × ... × S n → S łączy kilka strumieni wejściowych w jeden
strumień wynikowy. Rezultat zawiera wszystkie krotki S i dla i ∈< 1, n > . Warunkiem koniecznym
użycia unii jest zgodność meta-schematów strumieni wejściowych.
3.5 Operacja reorganizacji
Reorganizacja wyzwalana jest przez kolejne krotki przekazywane węzłowi na wejście zanim
zostaną jeszcze przetworzone. Jej zadaniem jest oczyszczanie operatora z elementów, których czas
życia upłynął [3].
Niech S1 ,..., S n ∈ S gdzie n ∈ N są strumieniami wejściowymi operatora. Na potrzebę operacji
reorganizacji przechowujemy najstarsze znaczniki czasu t s j gdzie j ∈ {1,..., n} krotek kolejnych
strumieni wejściowych oczekujących na przetworzenie. Każda krotka (e,[t s , te ) ) może zostać
bezpiecznie usunięta ze struktur wewnętrznych operatora jeżeli jej te jest mniejsze lub równe
{
}
min t s j | j ∈ {1,..., n} .
Wywołanie reorganizacji przed wykonaniem właściwej operacji węzła pozwala przyspieszyć
wyliczania wyników, ponieważ operator nie musi wówczas sprawdzać krotek, co do których mamy
pewność, że nie będą tworzyły wyniku.
3.6 Kolekcje krotek
Kolekcje służą przechowywaniu elementów pochodzących z jednego strumienia. Występują
one tylko w węzłach reprezentujących operatory stanowe. Po uwzględnieniu faktu, że każda krotka
ma ustalony czas życia oraz kolekcje mogą zasilać indeksy, obiekt kolekcji krotek udostępnia
następującą funkcjonalność:
1) przeglądanie zawartości zgodnie z porządkiem leksykograficznym,
2) wstawianie krotek,
3) realizacja operacji reorganizacji,
4) dostęp do krotek poprzez identyfikator numeryczny,
5) zgłaszanie wydarzeń o zmianie zawartości kolekcji:
•
usunięcie wpisu,
•
wstawienie wpisu,
•
aktualizacja wpisu,
•
reorganizacja.
Dodanie indeksów wyliczających relacje wiąże się z potrzebą zdefiniowania atrybutu
kluczowego. Jest on wartością numeryczną, jeżeli krotka nie definiuje takiego atrybutu wówczas
kolekcja automatycznie nadaje wartość unikalną kluczowi. Aby zapewnić spójność danych w
węźle, aktualizacja indeksu jest wywoływana natychmiast po aktualizacji kolekcji, na którym dany
indeks jest zbudowany.
Prezentowany system wspiera kolekcje:
1) czasowe,
2) czasowo-tabelaryczne.
Kolekcja czasowa:
− wstawianym krotką przypisywane są automatycznie unikalne wartości klucza,
− czas życia obiektów zależy od wartości atrybutów ts, te krotek,
− elementy kolekcji są usuwane w wyniku wywołania operacji reorganizacji.
Kolekcja czasowo-tabelaryczna:
− czas życia obiektów zależy od wartości atrybutów ts, te krotek,
− elementy kolekcji są usuwane w wyniku wywołania operacji reorganizacji,
− krotka zawiera atrybut kluczowy który steruje funkcjami: wstawiana, aktualizacji, zmiany
czasu życia krotki.
Przekazanie do kolekcji czasowo-tabelarycznej krotki o atrybucie kluczowym id skutkuje
operacją:
id krotki nie istnieje w zbiorze – krotka jest dodana do zbioru,
id krotki istnieje w zbiorze – krotka poprzednia jest zastąpiona nową,
id krotki jest liczbą ujemną – atrybut te krotki będącej w kolekcji jest zastępowany atrybutem te
nowej krotki.
Importowanie rekordów z tabel można zrealizować poprzez skopiowanie wartości atrybutów
do krotki, ustawieniu znacznika ts na bieżący czas oraz t e = ∞ . Operacja usuwania rekordu
odpowiada wysłaniu krotki o ujemnym identyfikatorze oraz przekazaniu informacji o czasie
usunięcia poprzez atrybut te. Właściwe usunięcie elementu z kolekcji ma miejsce dopiero podczas
fazy reorganizacji. Jeżeli zostanie wysłana krotka o identyfikatorze istniejącym już w kolekcji,
zastąpiony zostanie poprzedni wpis nowym, włącznie z aktualizacją znaczników czasu. Każda
operacja na krotce kolekcji wiąże się z aktualizacją znacznika ts, co ma na celu zagwarantowanie
niezmienności prefiksu krotek przetworzonych przez operator (zmiany nie obejmują historii).
3.7 Uporządkowanie krotek w strumieniach
Definicja 2.
Prefiksu sekwencji krotek: Pod-sekwencja krotek rozpoczynająca się od najstarszej kończąc na
krotce ze znacznikiem [ts,te) (korzystamy z porządku leksykograficznego).
Operatory zasilane kilkoma strumieniami wejściowymi wymagają przetwarzania krotek w
porządku leksykograficznym. Powyższa własność gwarantuje finalność generowanych wyników,
ponieważ nie modyfikujemy prefiksu krotek dla [ts,te).
Aby uniknąć konieczności przesyłania replik krotek w strumieniach reprezentujących zjawiska
o małej zmienności oraz w celu utrzymania płynności przetwarzania, wprowadzono krotkę typu
BOUNDARY [2]. Pełni ona rolę mechanizmu „bicia serca”. Znacznik czasowy krotki tego typu
(e,[t s , t s ) )
informuje, że kolejne elementy w strumieniu nie będą posiadały dat wcześniejszych.
Podobnie jak dla operacji reorganizacji, przechowujemy najstarsze znaczniki [t s j , t e j ) gdzie
j ∈ {1,..., n} krotek kolejnych strumieni wejściowych oczekujących na przetworzenie. Kolejna
krotka pobrana ze strumienia wejściowego i przekazana do dalszego przetwarzania spełnia
warunek:
{
}
[t s , t e ) ≤ ts ,te min [t s j , t e j ) | j ∈ {1,..., n}
k r o t k a z w y k ła
15
16
S t r u m ie ń S 1
S t r u m ie ń S 2
Rys. 3.
Fig. 3.
k ro tk a B O U N D A R Y
10
14
11
13
24
24
19
20
19
21
20
14
czas
Porządkowanie krotek strumieni wejściowych. Liczby w wierszach oznaczają
odpowiednio ts, te
Sorting the input streams tuples. The numbers in boxes denotes ts, te
Po przetworzeniu kolejek wejściowych z rys.3 pozostaną w kolejkach ostatnie obiekty. Krotka
BOUNDARY pozwoliła na przekazanie do dalszego przetworzenia obiekty o ts = 19, 19, 20.
Mechanizm ten rozwiązuje problem zachowania płynności przetwarzania w przypadku, gdy
strumienie rzadko nadsyłają krotki z danymi.
4 Język zapytań
4.1 Drzewa atrybutów
Dane w języku zapytań StreamAPAS v2.0 reprezentowane są jako drzewa atrybutów. Etykieta
korzenia wskazuje strumień systemu. Każdy z węzłów drzewa posiada nazwę, typ oraz
identyfikator atrybutu w krotce. Nie każdy węzeł struktury musi posiadać zdefiniowany typ. Takie
puste węzły tworzą strukturę danych czytelniejszą poprzez wprowadzenie zgrupowań. W poniższym przykładzie rolę tą pełni węzeł position.
Błąd! Nie można tworzyć obiektów przez edycję kodów pól.
Rys. 4. Przykład struktury drzewa etykiet
Fig. 5. Example of attribute tree
Ponieważ każda krotka posiada znacznik początku i końca życia ich identyfikatory mają
wartości stałe kolejno 0, 1. Chcąc odczytać atrybut I.position.x (rys.1) należy wpierw odczytać
wartość identyfikatora atrybutu, następnie pobrać atrybut o wskazanym identyfikatorze z krotki
strumienia.
Drzewo informacji jest reprezentowane przez zagnieżdżone listy atrybutów. Skorzystanie z
definicji, w której rozpatrywalibyśmy drzewo jako zagnieżdżone wielozbiory [6] nie pozwoliłoby
odwoływać się do atrybutów przy użyciu numeru porządkowego.
W
konsekwencji funkcje operujące na drzewach informacji mogłyby odwoływać się do atrybutów
tylko poprzez etykietę atrybutu. Przyjęcie koncepcji zagnieżdżonych list atrybutów pozwala
rozpoznawać atrybuty funkcji zgodnie z numerem porządkowym (tak jak ma to miejsce w
językach C/C++) lub na podstawie etykiety.
Dla danej zagnieżdżonej listy etykiet A, definiujemy listę LT atrybutów indeksowany poprzez I
tak, że:
-pusta lista etykiet {}, należy do LT,
-jeśli m występuje w A oraz I w LT, wtedy istnieje para {<m,I>} w LT,
-LT jest unią zagnieżdżonych list
U M ( j ) , gdzie J jest zbiorem indeksów i M ∈ J → LT .
j∈J
Przyjmując powyższą definicję drzewa etykiet, utworzono funkcję mapującą wyrażenie A na
atrybuty krotki strumienia.
η ::=
$nazwa
nazwa
A, B ::=
T
etykieta węzła drzewa
etykieta korzenia
etykieta węzła w bieżącym kontekście
wyrażenie
drzewo atrybutów począwszy od bieżącego kontekstu
η [ A] lokacja bieżącego kontekstu na węźle η
A , B kompozycja drzew atrybutów
Aby uprościć odwoływanie się do pojedynczych węzłów np. O[z[x = 1.1]] następujące po
sobie klamry można zastąpić „.”. Otrzymamy wtedy postać O.z.x = 1.1.
Na zdefiniowanej powyżej strukturze danych zostały zdefiniowane podstawowe operacje
matematyczne, logiczne oraz operacja kopiowania drzewa atrybutów.
Przykładowe wyrażenie:
O[z = $I.position.x + $I.position.y, $I. position[T]]
Domyślnym kontekstem etykiet jest lista nazw strumieni, dlatego nie ma potrzeby zapisu $O.
W podanym przykładzie występuje operacja przypisania z = … która tworzy nową etykietę o typie
zgodnym z wyliczeniem po prawej stronie. Jeżeli etykieta zostałaby wcześniej zdefiniowana,
wynik konwertowany byłby do zdefiniowanego typu. Jeżeli brak odpowiedniego rzutowania
nastąpi zgłoszenie błędu. W wyniku kompozycji …, $I.position do struktury wynikowej zostaną
skopiowane atrybuty ze wskazanego węzła. Należy zwrócić uwagę na prostotę przenoszenia ze
struktury źródłowej grupy zmiennych związanych ze sobą znaczeniowo.
Obliczenia etykiet wykonywane są zgodnie z kolejnością wystąpienia np.: O[z = $I.place.x +
$I.place.y, z = 1.0]
zostanie wyliczone
$O.z = $I.place.x + $I.place.y
$O.z = 1.0
4.2 Składnia zapytania
Pojedyncze zapytanie przetwarzania strumieniowego to sieć powiązanych ze sobą pod-zapytań.
Po słowie kluczowym from następuje definicja kolejnych strumieni wewnątrz tej sieci. Na koniec
w frazie select podajemy strumień wynikowy zdefiniowany na jednym ze strumieni wewnętrznych.
Lista strumieni źródłowych potrzebna do budowy pod-zapytań wyznaczana jest na podstawie
analizy atrybutów w frazie select i where.
Składnia języka:
from
{<deklaracja strumienia>;}
selekt <wyliczenie wartości atrybutów>
Deklaracja strumienia:
uproszczona
<wyliczenie wartości atrybutów>
pełna
where wyrażenie operatorowe
select <wyliczenie wartości atrybutów>
operatory – operacja: łączenia, filtracji, okno czasowe, funkcja relacyjna (np. implementacja
indeksu), unii
wyliczenie wartości atrybutów – definicja drzewa atrybutów dla strumienia wynikowego,
można skorzystać z funkcji agregacyjnej
Prezentowany język posiada następującą składnię okien czasowych:
window.range(source, time) – realizuje funkcję okna zakresowego.
window.fixed(source, time) – realizuje funkcję okna z stałymi interwałami czasu.
window.infinite(source) – realizuje funkcję okna gromadzącego wszystkie krotki.
Atrybuty:
source – nazwa strumienia zasilającego np. $I
time – stała wartość definiująca interwał czasu np. 10s
Domyślną kolekcją krotek dla operatorów stanowych jest kolekcja czasowa. Jeżeli chcemy
skorzystać z innej podajemy tą informację w frazie where. Alternatywą dla domyślnej kolekcji
czasowej jest kolekcja czasowo-tablearyczna o składni:
window.table(source)
Atrybuty:
source – nazwa atrybutu będącego kluczem głównym krotki; atrybut musi być typu
numerycznego. Dzięki zastosowaniu drzewa atrybutów nazwa strumienia jest
elementem atrybutu source np. $I.id.
Operatory stanowe mogą być zdefiniowane na kilku strumieniach, zatem występuje wiele
konfiguracji okien czasowych. Przeanalizujmy działanie operacji łączenia zdefiniowanej: $I.a ==
$II.a ze względu na konfigurację okien czasowych (tab. 2). Przyjmijmy że dane źródłowe mają
wstępnie ustawiony czas życia na zero.
Tab. 1.
Konfiguracje okien dla operacji łączenia
Sytuacja
Okno dla I
Okno dla II
Wynik relacji
1
brak
Brak
kolekcje pozostają puste, brak krotek wynikowych
2
istnieje
Brak
krotka ze zbioru $II jest dopasowywana do kolekcji
krotek z okna $I. Przy czym krotki $I nie są
dopasowywane do $II
3
istnieje
Istnieje
Zarówno pojawienie się krotki na wyjściu strumienia $I
jak i $II skutkuje rozpoczęciem operacji łączenia
Sytuacja 1 to błąd użytkownika, który nie zdefiniował w pełni zapytania, przy czym nie ma
ryzyka utworzenia kolekcji nieskończonej.
Sytuację 2 ilustruje przykład: „Jesteśmy zainteresowani zbiorem (strumień $I) pojazdów z
ostatnich 5 min, których szybkość przekroczyła zadaną wartość” (strumień $II).
Rozbudowując powyższy przykład ilustrujemy sytuację 3: „Jesteśmy zainteresowani zbiorem
(strumień $I) pojazdów z ostatnich 5min, których szybkość będzie przekraczała zadaną wartość
(strumień $II) przez najbliższą godzinę”.
4.3 Przykładowe zapytanie
Zaprezentowane poniżej zapytanie może służyć wskazaniu trzech najbliższych stacji
serwisowych dla każdego z nadzorowanych samochodów. Przyjmijmy, że strumień I zawiera
informacje o bieżącym położeniu przemieszczających się obiektów a strumień II przekazuje
informacje o położeniu stacji serwisowych.
from
where window.table($service.id) AND
util.knn([$car.point[T], k = 3], $service[T])
select sol[
name = $car.id,
query = $car.point[T],
service = $service.point[T]];
select out[$sol[T]]
Widzimy tutaj zaletę stosowania drzewiastej struktury atrybutów. Jeżeli dobrze zaprojektuje się
schematy strumieni w systemie StreamAPAS v2.0, to korzystanie z funkcji sprowadza się do
wskazania węzłów struktury atrybutów strumienia, z których będą pobierane dane. Unikamy w ten
sposób konieczności wielokrotnego podawania długiej listy atrybutów. Powyższy przykład
korzysta również z tymczasowego drzewa atrybutów, które służy rozszerzeniu zbioru atrybutów
strumienia zasilającego o atrybut zawierający liczbę poszukiwanych najbliższych sąsiadów.
5 Literatura
1.
2.
3.
4.
5.
6.
7.
8.
9.
Marcin Gorawski, Skierski Andrzej : „Okienkowy język zapytań. II Krajowa Konferencja
Naukowa Technologie Przetwarzania Danych”, 24-26 września 2007, Poznań, Polska.
Magdalena Balazinska: „Fault-tolerance and load management in a Distributed Stream
Processing System”, PhD dissertation, Massachusetts institute of technology, February 2006
Joürgen Krämer, Bernhard Seeger: „A Temporal Foundation for Continuous Queries over Data
Streams”, Department of Mathematics and Computer Science PhilippsUniversity, Marburg,
Germany, 11th International Conference on Management of Data (COMAD 2005)
Arvind Arasu, Shivnath Babu, Jennifer Widom: „The CQL Continuous Query Language
Semantic Foundations and Query Execution”, Stanford University, the International Journal on
Very Large Databases (VLDB Journal) June 2006, 15:2 121-142
Songmei Yu, Vijayalashmi Atluri, Nabil Adam: „Optimizing View Materialization Cost in
Spatial Data Warehouses”, Lecture Notes in Computer Science 4081 Springer 2006, 45-54
Luca Ardelli, Giorgio Ghelli: „TQL: A Query Language for Semistructured Data Based on the
Ambient logic” MATHEMATICAL STRUCTURES IN COMPUTER SCIENCE 2004, VOL
14; PART 3, pages 285-328
Daniel Johannes, Pieter Leijen: „The λ Abroad – A Functional Approach To Software
Components” Daan Leijen. PhD thesis, Department of Computer Science, Utrecht University,
November 2003
Radosław Grabowski, Artur Wilczek: „Przetwarzanie strumieni danych z zastosowaniem
relacyjnego systemu zarządzania bazą danych”, XIV Konferencja Systemy czasu
rzeczywistego, 10-13.09.2007, Karpacz, Polska
Peter A.Tucker: „Punctuated Data Streams” PhD dissertation, OGI School of Science &
Technology At Oregon Health & Science University, August 2005

Podobne dokumenty