Dobry przegląd
Mówiąc ogólnie, podejmujesz decyzję pomiędzy szybkim czasem odczytu (na przykład zestawem zagnieżdżonym) lub szybkim czasem zapisu (lista sąsiadów). Zwykle kończy się kombinacją poniższych opcji, które najlepiej pasują do twoich potrzeb. Poniżej przedstawiono dogłębną lekturę:
- Jeszcze jedno porównanie przedziałów zagnieżdżonych a porównanie listy adiakencji : najlepsze porównanie , jakie znalazłem, listy adiakencji, zmaterializowanej ścieżki, zestawu zagnieżdżonego i przedziału zagnieżdżonego.
- Modele danych hierarchicznych : slajdy z dobrymi objaśnieniami dotyczącymi kompromisów i przykładowego użycia
- Reprezentowanie hierarchii w MySQL : szczególnie bardzo dobry przegląd zestawu zagnieżdżonego
- Hierarchiczne dane w RDBMS : najbardziej kompleksowy i dobrze zorganizowany zestaw linków, jaki widziałem, ale niewiele w wyjaśnieniu
Opcje
Te, które znam i ogólne cechy:
- Lista adiakencji :
- Kolumny: ID, ParentID
- Łatwy do wdrożenia.
- Tanie przesuwanie, wstawianie i usuwanie węzłów.
- Drogie, aby znaleźć poziom, pochodzenie i potomkowie, ścieżkę
- Unikaj N + 1 poprzez wspólne wyrażenia tabel w bazach danych, które je obsługują
- Zestaw zagnieżdżony (znany również jako zmodyfikowane przemierzanie drzewa w przedsprzedaży )
- Kolumny: lewy, prawy
- Tanie pochodzenie, potomkowie
- Bardzo drogie
O(n/2)
ruchy, wstawianie, usuwanie z powodu niestabilnego kodowania
- Stolik pomostowy (inaczej zwany stołem zamknięcia / wyzwalaczami )
- Używa oddzielnej tabeli łączenia z: przodkiem, potomkiem, głębokością (opcjonalnie)
- Tanie pochodzenie i potomkowie
- Zapisuje koszty
O(log n)
(wielkość poddrzewa) dla wstawiania, aktualizacji, usuwania - Znormalizowane kodowanie: dobre dla statystyk RDBMS i planowania zapytań w złączeniach
- Wymaga wielu wierszy na węzeł
- Kolumna linii (aka zmaterializowana ścieżka , wyliczenie ścieżki)
- Kolumna: rodowód (np. / Rodzic / dziecko / wnuk / etc ...)
- Tanie potomkowie poprzez zapytanie o prefiks (np.
LEFT(lineage, #) = '/enumerated/path'
) - Zapisuje koszty
O(log n)
(wielkość poddrzewa) dla wstawiania, aktualizacji, usuwania - Nierelacyjny: opiera się na typie danych macierzy lub formacie ciągu szeregowego
- Zagnieżdżone interwały
- Jak zestaw zagnieżdżony, ale z rzeczywistym / zmiennoprzecinkowym / dziesiętnym, dzięki czemu kodowanie nie jest ulotne (niedrogi ruch / wstaw / usuń)
- Ma problemy z rzeczywistą / zmienną / dziesiętną reprezentacją / precyzją
- Wariant kodowania matrycowego dodaje kodowanie przodka (zmaterializowaną ścieżkę) dla „wolnego”, ale z dodatkową trudnością algebry liniowej.
- Płaski stół
- Zmodyfikowana lista Adjacency, która dodaje kolumnę Poziom i Pozycja (np. Kolejność) do każdego rekordu.
- Tanie iteracja / paginacja
- Drogie przenoszenie i usuwanie
- Dobre wykorzystanie: dyskusja w wątkach - komentarze na forach / blogach
- Wiele kolumn linii
- Kolumny: jedna dla każdego poziomu linii, odnosi się do wszystkich rodziców aż do katalogu głównego, poziomy w dół od poziomu elementu są ustawione na NULL
- Tanie przodkowie, potomkowie, poziom
- Tanie wstawianie, usuwanie, przenoszenie liści
- Drogie wstawianie, usuwanie, przenoszenie wewnętrznych węzłów
- Twardy limit głębokości hierarchii
Uwagi dotyczące bazy danych
MySQL
Wyrocznia
- Użyj CONNECT BY, aby przeglądać listy Adjacency
PostgreSQL
- Typ danych dla ścieżki zmaterializowanej
SQL Server
- Ogólne podsumowanie
- Oferty z 2008 r. Typ danych HierarchyId wydaje się pomagać w podejściu do kolumny linii i zwiększać głębokość, którą można przedstawić.
sql
database
tree
relational-database
hierarchical-data
orangepips
źródło
źródło
Closure Tables
są lepszeAdjacency List
,Path Enumeration
aNested Sets
pod względem łatwości użycia (i zgaduję wydajności, jak również).Odpowiedzi:
Moją ulubioną odpowiedzią jest to, co sugeruje pierwsze zdanie w tym wątku. Użyj listy Adjacency, aby utrzymać hierarchię, a za pomocą zestawów zagnieżdżonych zapytaj hierarchię.
Do tej pory problem polegał na tym, że metoda krycia z listy Adjacecy do zestawów zagnieżdżonych była strasznie powolna, ponieważ większość osób korzysta z ekstremalnej metody RBAR znanej jako „Push Stack” do konwersji i uważana jest za zbyt kosztowną aby osiągnąć nirwanę prostoty konserwacji dzięki liście Adjacency i niesamowitej wydajności zestawów zagnieżdżonych. W rezultacie większość ludzi ostatecznie musi zadowolić się jednym lub drugim, szczególnie jeśli jest ich więcej niż, powiedzmy, kiepskie 100 000 węzłów. Korzystanie z metody wypychania stosu może zająć cały dzień, aby wykonać konwersję według tego, co MLM uważają za hierarchię milionów węzłów.
Pomyślałem, że dałbym Celko trochę konkurencji, wymyślając metodę konwersji Listy Adjacencji na zestawy zagnieżdżone z prędkościami, które po prostu wydają się niemożliwe. Oto wydajność metody wypychania stosu na moim laptopie i5.
Oto czas trwania nowej metody (z metodą wypychania stosu w nawiasach).
Tak, to jest poprawne. 1 milion węzłów przekonwertowanych w mniej niż minutę i 100 000 węzłów w mniej niż 4 sekundy.
Możesz przeczytać o nowej metodzie i uzyskać kopię kodu pod następującym adresem URL. http://www.sqlservercentral.com/articles/Hierarchy/94040/
Opracowałem również „wstępnie zagregowaną” hierarchię przy użyciu podobnych metod. MLM i osoby sporządzające zestawienia materiałowe będą szczególnie zainteresowane tym artykułem. http://www.sqlservercentral.com/articles/T-SQL/94570/
Jeśli zajrzysz do jednego z artykułów, przejdź do linku „Dołącz do dyskusji” i daj mi znać, co myślisz.
źródło
To jest bardzo częściowa odpowiedź na twoje pytanie, ale mam nadzieję, że nadal będzie przydatna.
Microsoft SQL Server 2008 implementuje dwie funkcje, które są niezwykle przydatne do zarządzania danymi hierarchicznymi:
Na początek spójrz na „Modeluj swoje hierarchie danych za pomocą SQL Server 2008” autorstwa Kent Tegels na MSDN. Zobacz także moje własne pytanie: zapytanie rekursywne w tej samej tabeli w SQL Server 2008
źródło
Ten projekt nie został jeszcze wspomniany:
Wiele kolumn linii
Chociaż ma ograniczenia, jeśli możesz je znieść, jest bardzo prosty i bardzo wydajny. Funkcje:
Oto przykład - taksonomiczne drzewo ptaków, więc hierarchia to Klasa / Porządek / Rodzina / Rodzaj / Gatunek - gatunek jest najniższym poziomem, 1 wiersz = 1 takson (co odpowiada gatunkowi w przypadku węzłów liści):
i przykład danych:
Jest to świetne, ponieważ w ten sposób wykonujesz wszystkie potrzebne operacje w bardzo łatwy sposób, o ile kategorie wewnętrzne nie zmieniają swojego poziomu w drzewie.
źródło
Model adiacyencji + model zestawów zagnieżdżonych
Poszedłem za tym, ponieważ mogłem łatwo wstawiać nowe elementy do drzewa (wystarczy identyfikator gałęzi, aby wstawić do niego nowy element), a także dość szybko odpytywać.
parent
kolumnę.lft
między nimilft
argt
rodzicem.lft
niższej niż węzełlft
irgt
większej niż węzełrgt
i sortujesz wedługparent
.Musiałem sprawić, aby dostęp do drzewa i zapytania do niego były szybsze niż wstawki, dlatego właśnie to wybrałem
Jedynym problemem jest naprawa kolumn
left
iright
podczas wstawiania nowych elementów. Cóż, stworzyłem dla niego procedurę składowaną i wywoływałem ją za każdym razem, gdy wstawiałem nowy element, co w moim przypadku było rzadkie, ale jest naprawdę szybkie. Pomysł zaczerpnąłem z książki Joe Celko, a procedura składowana i sposób, w jaki ją wymyśliłem, wyjaśniono tutaj w DBA SE https://dba.stackexchange.com/q/89051/41481źródło
children
idescendants
.left
iright
służą do znajdowania potomków.Jeśli baza danych obsługuje tablice, możesz także zaimplementować kolumnę linii lub zmaterializowaną ścieżkę jako tablicę identyfikatorów nadrzędnych.
W szczególności za pomocą Postgresa można następnie użyć operatorów zestawów do przeszukiwania hierarchii i uzyskania doskonałej wydajności dzięki indeksom GIN. To sprawia, że znalezienie rodziców, dzieci i głębokości jest bardzo proste w jednym zapytaniu. Aktualizacje są również łatwe do zarządzania.
Mam pełny opis używania tablic dla zmaterializowanych ścieżek, jeśli jesteście ciekawi.
źródło
To jest naprawdę kwadratowy kołek, pytanie z okrągłymi otworami.
Jeśli relacyjne bazy danych i SQL są jedynymi młotami, które masz lub chcesz użyć, to odpowiedzi, które zostały opublikowane do tej pory, są odpowiednie. Dlaczego jednak nie skorzystać z narzędzia zaprojektowanego do obsługi danych hierarchicznych? Baza danych wykresów jest idealna dla złożonych danych hierarchicznych.
Nieefektywność modelu relacyjnego wraz ze złożonością dowolnego rozwiązania kodu / zapytania w celu odwzorowania modelu graficznego / hierarchicznego na model relacyjny nie jest po prostu warta wysiłku w porównaniu z łatwością, z jaką rozwiązanie bazy danych wykresów może rozwiązać ten sam problem.
Rozważ listę materiałów jako wspólną hierarchiczną strukturę danych.
Najkrótsza ścieżka między dwoma podzespołami : Prosty algorytm przechodzenia przez wykres. Dopuszczalne ścieżki można zakwalifikować na podstawie kryteriów.
Podobieństwo : Jaki jest stopień podobieństwa między dwoma zespołami? Wykonaj przemieszczenie obu pod-drzew, obliczając przecięcie i połączenie dwóch pod-drzew. Procent podobny to przecięcie podzielone przez związek.
Przejściowe zamknięcie : przejdź się do sub-drzewa i zsumuj interesujące pola, np. „Ile aluminium jest w podzespole?”
Tak, możesz rozwiązać problem za pomocą SQL i relacyjnej bazy danych. Istnieją jednak znacznie lepsze podejścia, jeśli chcesz użyć odpowiedniego narzędzia do pracy.
źródło
Używam PostgreSQL z tabelami zamknięcia dla moich hierarchii. Mam jedną uniwersalną procedurę składowaną dla całej bazy danych:
Następnie dla każdej tabeli, w której mam hierarchię, tworzę wyzwalacz
Do zapełniania tabeli zamknięcia z istniejącej hierarchii używam tej procedury składowanej:
Tabele zamknięcia są zdefiniowane za pomocą 3 kolumn - ANCESTOR_ID, DESCENDANT_ID, DEPTH. Możliwe jest (a nawet doradzam) przechowywanie rekordów o tej samej wartości dla ANCESTOR i DESCENDANT oraz o wartości zero dla DEPTH. Uprości to zapytania dotyczące pobierania hierarchii. I są naprawdę bardzo proste:
źródło