Modelowanie hierarchicznych struktur w relacyjnych bazach danych Wiktor Warmus (wiktorwarmus@gmail.com) Kamil Witecki (kamil@witecki.net.pl) 5 maja 2010
Motywacje Teoria relacyjnych baz danych Do czego potrzebujemy struktur hierarchicznych? Hierarchiczną strukturą danych nazwiemy strukturę, która można reprezentować za pomocą drzewa (grafu spójnego bez cykli) Przykładowe zastosowania w aplikacjach Modelowanie kategorii w sklepie, na blogach itp. Zagnieżdżone tematy na forach Modelowanie zależności zadań i zasobów
Rodzaje notacji Motywacje Teoria relacyjnych baz danych Rachunek domen, rachunek relacji Projekcja Π a1,...,a n (R) - rzutowanie krotek relacji R na zbiór atrybutów a 1,..., a n Selekcja σ ϕ (R) wybór podzbioru krotek z relacji R spełniających formułę logiczną ϕ Operacje na zbiorach,, \ Złączenia, SQL - Structured Query Language
Normalizacja Motywacje Teoria relacyjnych baz danych Przez normalizację bazy danych rozumiemy proces zmniejszający jej wrażliwość na utratę spójności podczas wykonywania operacji modyfikujących zawartość Normalizacja bazy danych ma na celu wykluczenie sytuacji w których: Część rekordów nie zostanie zaktualizowana Część informacji zostanie bezpowrotnie i przypadkowo utracona Dwa rekordy o tym samym kluczu będą miały różne wartości atrybutów
Opracowane modele Lista sąsiedztwa, zagnieżdżone zbiory, materializowana ścieżka, znormalizowana materializowana ścieżka albo tranzytywne domknięcie listy sąsiedztwa
Model teoretyczny Bezpośrednie przełożenie drzewa na bazę danych Każdy rekord wskazuje na rekord - rodzica Tabela: Przykładowy schemat listy sąsiedztwa id parent id 1 1 2 1 3 1 4 3 5 2
Operacje na drzewie I Dodawanie węzłów INSERT INTO t r e e SET p a r e n t i d = 2 ; Usuwanie wezłów DELETE FROM t r e e WHERE id = 1 ;
Operacje na drzewie II Zmiana rodzica danego węzła UPDATE t r e e WHERE id = 4 SET p a r e n t i d = 3 ; Pobranie dzieci danego wezła SELECT FROM t r e e WHERE p a r e n t i d = 1 ;
Operacje na drzewie III Pobranie poddrzewa danego węzła (posortowanego względem pokolenia) Problem z ustaleniem głebokości drzewa przed jego pobraniem SELECT FROM t r e e as l e v e l 1 WHERE p a r e n t i d = 1 UNION SELECT FROM t r e e WHERE p a r e n t i d IN (SELECT FROM t r e e as l e v e l 1 WHERE p a r e n t i d = 1 ) ; Pobranie listy rodziców (od korzenia) rodzi identyczne problemy, jak poprzednie zapytanie
I Zalety Koncepcyjnie prosta - łatwo zrozumieć działanie listy. Nie wymaga dodatkowych atrybutów - można wprowadzić hierarchę w dowolnej relacji dodając relację sąsiedztwa. Łatwo serializować obiekty drzewiaste tworzone na zasadzie przechowywania wskaźnika do rodzica i wskaźników do dzieci.
II Wady Wymaga rekursji, a nie wszystkie bazy danych obsługują takową. Nie wprowadza żadnej abstrakcji, przez co modyfikacja identyfikatorów może modyfikować drzewo. Problem ze wskazaniem rodzica - NULL psuje indeksowanie, wskazanie na samego siebie jest nieintuicyjne. Nie ma porządku pomiędzy dziećmi danego węzła.
Model teoretyczny I Reprezentacja węzłów w drzewie jako zbiorów Element jest dzieckiem danego węzła jeśli jest jego podzbiorem Tabela: Przykładowy schemat zagnieżdżonych zbiorów id left right 1 1 10 2 2 5 3 6 9 4 7 8 5 3 4
Model teoretyczny II Elementy posiadają dwa dodatkowe atrybuty - left i right, określające ich granice Wymuszamy by A,B R (A < B B < A), gdzie R to nasza relacja, a < oznacza relację Bycia dzieckiem
Model teoretyczny III Rysunek: Graficzna reprezentacja zagnieżdżonych zbiorów 1 2 3 1 2 3 4 4 5 6 7 5 8 9 10
Operacje na drzewie I Dodawanie węzłów UPDATE t r e e SET right = right + 2 WHERE l e f t >= (SELECT l e f t FROM t r e e WHERE id = 2 ) l e f t <= (SELECT l e f t FROM t r e e WHERE id = 2 ) ; INSERT INTO t r e e SET l e f t = (SELECT right 2 FROM t r e e WHERE id = 2 ), right = (SELECT right 1 FROM t r e e WHERE id = 2 ) ;
Operacje na drzewie II Usuwanie wezłów UPDATE t r e e SET right = right 2 WHERE id = (SELECT parent. id FROM t r e e AS parent JOIN t r e e as node WHERE node. l e f t BETWEEN parent. l e f t AND parent. right AND id = 1 ) ; DELETE FROM t r e e WHERE id = 1 ;
Operacje na drzewie III Zmiana rodzica danego węzła
Operacje na drzewie IV UPDATE t r e e SET right = right 2 WHERE id = (SELECT parent. id FROM t r e e AS parent JOIN t r e e as node WHERE node. l e f t BETWEEN parent. l e f t AND parent. right AND id = 1 ) ; UPDATE t r e e SET right = right + 2 WHERE l e f t >= (SELECT l e f t FROM t r e e WHERE id = 2 ) l e f t <= (SELECT l e f t FROM t r e e WHERE id = 2 ) ; UPDATE t r e e SET l e f t = (SELECT right 2 FROM t r e e WHERE id = 2 ), right = (SELECT right 1 FROM t r e e WHERE id = 2 ) ;
I Zalety Nie wymaga rekurencji - umożliwia pobranie dowolnego fragmentu poddrzewa przy pomocy pojedynczego zapytania! Umożliwia bardzo dobre indeksowanie warunków wyszukiwania. Można łatwo określić, czy dany element jest liściem. porządku następuje przez porównanie atrybutu left dwóch sąsiadów.
II Wady Jest mocno skomplikowany, powoduje wiele problemów ze zrozumieniem operacji na drzewie i ich poprawną implementacją. Pobranie listy rodziców wymaga określenia nadzbioru par left i right. Wymaga użycia indeksów geometrycznych w celu poprawy wydajności.
Model teoretyczny I Reprezentacja zależności w postaci ścieżki np. /1/5/6/ Element jest dzieckiem danego węzła jeśli jego ścieżka leży wewnątrz ścieżki rodzica Tabela: Przykładowy schemat zagnieżdżonych zbiorów id path 1 / 2 /1/ 3 /1/ 4 /1/3/ 5 /1/2/ Z każdym elementem związany jest atrybut ścieżki
Operacje na drzewie I Dodawanie węzłów INSERT INTO t r e e SET path = (SELECT CONCAT( path, /, id ) FROM t r e e WHERE id = 2 ) ;
Operacje na drzewie II Usuwanie wezłów (budzi wątpliwości!) DELETE FROM t r e e WHERE path LIKE (SELECT CONCAT( path, % ) FROM t r e e WHERE id = 1 ) ; DELETE FROM t r e e WHERE id = 1 ;
Operacje na drzewie III Zmiana rodzica danego węzła UPDATE t r e e SET path = REPLACE( /1/, /2/, path ) WHERE path LIKE (SELECT CONCAT( path, % ) FROM t r e e WHERE id = 3 ) ;
Operacje na drzewie IV Pobranie dzieci danego wezła SELECT FROM t r e e WHERE path REGEXP (SELECT CONCAT( path, [ˆ/]+/ ) FROM t r e e WHERE id = 1) AND ; Pobranie poddrzewa danego węzła (posortowanego względem pokolenia)
Operacje na drzewie V SELECT FROM t r e e WHERE path LIKE (SELECT CONCAT( path, % ) FROM t r e e WHERE id = 1) Pobranie listy rodziców (od korzenia) można wykonać rozparsowując ścieżkę po stronie aplikacji SELECT pt. FROM t r e e JOIN t r e e AS pt WHERE t r e e. path LIKE CONCAT( pt. path, % )
I Zalety Wady Nie wymaga rekurencji - umożliwia pobranie dowolnego fragmentu poddrzewa przy pomocy pojedynczego zapytania! Można łatwo określić, czy dany element jest liściem. Jest bardzo intuicyjny Tabele z materializowana scieżką są zdenormalizowanie Wymaga operacji na ciągach znaków, co psuje optymalizacje indeksami Nie można wprowadzić porządku pomiędzy elementami na tym samym poziomie
Model teoretyczny I Elementy są spokrewnione gdy istnieje odpowiedni rekord Tabela: Przykładowy schemat zagnieżdżonych zbiorów id id parent depth 1 1 0 2 1 1 2 2 0 3 1 1 3 3 0 4 1 2 4 3 1 4 4 0 5 1 1 5 5 0
Model teoretyczny II Reprezentacja zależności w postaci wskaźników na przodków z uwzględnieniem względnego zagnieżdżenia
Operacje na drzewie I Dodawanie węzłów INSERT INTO n m p r e l a t i o n SET node id = 2, p a r e n t i d = 1, depth =1; INSERT INTO n m p r e l a t i o n SELECT 2 as node id, p a r e n t i d, depth +1 FROM n m p r e l a t i o n WHERE node id =1;
Operacje na drzewie II Usuwanie wezłów (budzi wątpliwości!) DELETE FROM n m p r e l a t i o n WHERE node id = 1 OR p a r e n t i d = 1 ; Zmiana rodzica danego węzła UPDATE n m p r e l a t i o n SET p a r e n t i d = 3 WHERE node id = 2 ;
Operacje na drzewie III Pobranie dzieci danego wezła SELECT node id FROM n m p r e l a t i o n WHERE p a r e n t i d = 1 AND depth = 1 ; Pobranie poddrzewa danego węzła (posortowanego względem pokolenia) SELECT node id FROM n m p r e l a t i o n WHERE p a r e n t i d = 1 ORDER BY depth ;
Operacje na drzewie IV Pobranie listy rodziców (od korzenia) SELECT p a r e n t i d FROM n m p r e l a t i o n WHERE node id = 1 ORDER BY depth ;
I Zalety Wady Nie wymaga rekurencji - umożliwia pobranie dowolnego fragmentu poddrzewa przy pomocy pojedynczego zapytania! Jest bardzo wydajny W rzeczywistości stanowi domknięcie relacji listy sąsiedztwa Jest łatwy w zrozumieniu i zarządzaniu Wymaga dodatkowej tabeli i wielu dodatkowych rekordów
Wnioski Lista sąsiedztwa jest bardzo prosta. Dzięki temu implementacja jest szybka. Niestety - obarczona jest poważnymi problemami. Materializowana ścieżka i zagnieżdżone zbiory umożliwiają wydajniejsze wykonywanie operacji kosztem skomplikowania modelu. Pobranie rodziców w modelach zagnieżdżonych zbiorów i materializowanej ścieżki wymaga niestety przeszukiwania tablicy. Zawsze mamy alternatywę.
Podziękowania Dziękujemy za uwagę i zapraszamy na kolejny wykład.