SlideShare une entreprise Scribd logo
1  sur  10
Télécharger pour lire hors ligne
Nested Sets
Modified Preorder Tree Traversal (MPTT)
Die klassische Baum Implementation
(Adjacency list)
class TreeNode():
parent = models.ForeignKey(‘self’,
null=True)
value = models.CharField()
Zugriff auf ein Element
class TreeNode():
parent = models.ForeignKey(‘self’, null=True)
value = models.CharField()
def has_children(self, tree):
for node in tree:
if node.parent == self:
return True
return False
def get_children(self, tree):
children = [n for n in tree if
n.parent=self]
for child in children[:]:
children.extend(child.get_children(tree))
return children
Zugriff auf ein Element
Laufzeitkomplexität:
● Überprüfen, ob ein Knoten ein Blatt ist: O(n)
● Alle Kinder eines Knotens zurückgeben: O((tiefe+1)*n)
= O(n), fällt aber bei grossen Bäumen trotzdem ins
Gewicht.
● Knoten einfügen/löschen O(1)
Nested Sets
class TreeNode():
value = models.CharField()
left = models.IntegerField()
right = models.IntegerField()
Zugriff auf ein Element
class TreeNode():
value = models.CharField()
left = models.IntegerField()
right = models.IntegerField()
def has_children(self):
return self.right - self.left > 1
def get_children(self, tree):
return [n for n in tree if
n.left > self.left and
n.right < self.right]
Zugriff auf ein Element
Laufzeitkomplexität:
● Überprüfen, ob ein Knoten ein Blatt ist: O(1)
● Alle Kinder eines Knotens zurückgeben: O(log n)
● Knoten einfügen/löschen: O(n * log n)
○ Jede Zeile in der DB rechts vom geänderten Knoten
muss geändert werden.
○ Tabelle wird während dem Update gesperrt.
Performance-Vergleiche MySQL
Bsp: Tabelle mit 8 Hierarchiestufen und 2 Mio Einträge.
Die Abfragen sind auf das DBMS optimiert.
MySQL Nested Set Adjacency List
Alle Kinder eines
Elements (200k)
300ms 7s
Alle Eltern eines Elements
(9)
15ms (R-Tree Index) 600ms
Kinder bis 2 Level tiefer
(221)
5s 600ms
Performance-Vergleiche PostgreSQL
Bsp: Tabelle mit 8 Hierarchiestufen und 2 Mio Einträge.
Die Abfragen sind auf das DBMS optimiert.
PostgreSQL Nested Set Adjacency List
Alle Kinder eines
Elements (200k)
50ms 98ms
Alle Eltern eines Elements
(9)
2s 4ms (rekursiv)
Kinder bis 2 Level tiefer
(221)
121s 5ms (rekursiv)
Django Bibliotheken
● Nested Set Implementation für Django
● Speichert auch parent_id und level. Dadurch wird die Abfrage beschleunigt, aber Änderungen
werden noch komplexer.
● Erweitert das List-Admin um eine Baum-Funktion
● Enthält Template-Tags für das Rendering eines Baumes, z.B. für die Navgation.
● https://github.com/django-mptt/django-mptt
● https://github.com/tabo/django-treebeard/blob/master/treebeard/ns_tree.py

Contenu connexe

Nested sets

  • 1. Nested Sets Modified Preorder Tree Traversal (MPTT)
  • 2. Die klassische Baum Implementation (Adjacency list) class TreeNode(): parent = models.ForeignKey(‘self’, null=True) value = models.CharField()
  • 3. Zugriff auf ein Element class TreeNode(): parent = models.ForeignKey(‘self’, null=True) value = models.CharField() def has_children(self, tree): for node in tree: if node.parent == self: return True return False def get_children(self, tree): children = [n for n in tree if n.parent=self] for child in children[:]: children.extend(child.get_children(tree)) return children
  • 4. Zugriff auf ein Element Laufzeitkomplexität: ● Überprüfen, ob ein Knoten ein Blatt ist: O(n) ● Alle Kinder eines Knotens zurückgeben: O((tiefe+1)*n) = O(n), fällt aber bei grossen Bäumen trotzdem ins Gewicht. ● Knoten einfügen/löschen O(1)
  • 5. Nested Sets class TreeNode(): value = models.CharField() left = models.IntegerField() right = models.IntegerField()
  • 6. Zugriff auf ein Element class TreeNode(): value = models.CharField() left = models.IntegerField() right = models.IntegerField() def has_children(self): return self.right - self.left > 1 def get_children(self, tree): return [n for n in tree if n.left > self.left and n.right < self.right]
  • 7. Zugriff auf ein Element Laufzeitkomplexität: ● Überprüfen, ob ein Knoten ein Blatt ist: O(1) ● Alle Kinder eines Knotens zurückgeben: O(log n) ● Knoten einfügen/löschen: O(n * log n) ○ Jede Zeile in der DB rechts vom geänderten Knoten muss geändert werden. ○ Tabelle wird während dem Update gesperrt.
  • 8. Performance-Vergleiche MySQL Bsp: Tabelle mit 8 Hierarchiestufen und 2 Mio Einträge. Die Abfragen sind auf das DBMS optimiert. MySQL Nested Set Adjacency List Alle Kinder eines Elements (200k) 300ms 7s Alle Eltern eines Elements (9) 15ms (R-Tree Index) 600ms Kinder bis 2 Level tiefer (221) 5s 600ms
  • 9. Performance-Vergleiche PostgreSQL Bsp: Tabelle mit 8 Hierarchiestufen und 2 Mio Einträge. Die Abfragen sind auf das DBMS optimiert. PostgreSQL Nested Set Adjacency List Alle Kinder eines Elements (200k) 50ms 98ms Alle Eltern eines Elements (9) 2s 4ms (rekursiv) Kinder bis 2 Level tiefer (221) 121s 5ms (rekursiv)
  • 10. Django Bibliotheken ● Nested Set Implementation für Django ● Speichert auch parent_id und level. Dadurch wird die Abfrage beschleunigt, aber Änderungen werden noch komplexer. ● Erweitert das List-Admin um eine Baum-Funktion ● Enthält Template-Tags für das Rendering eines Baumes, z.B. für die Navgation. ● https://github.com/django-mptt/django-mptt ● https://github.com/tabo/django-treebeard/blob/master/treebeard/ns_tree.py