hunderte Kategorien Abspeichern und ausgeben
bearbeitet von Rolf BHallo Bernd. Oder bist Du Michael?
verstehe ich das richtig? Die Query zählt für jede Kategorie, in wievielen Ober-Ebenen sie enthalten ist (wobei sie sich selbst mitzählt; X BETWEEN A AND B ist ein A <= X <= B Vergleich), und filtert dann die, wo der Zähler den Wert 2 annimmt. Du würdest hier also die Kategorien der zweiten Ebene bestimmen.
Allerdings ist dieses Statement unglaublich komplex. Der Server muss hier pro Kategorie (Zeile aus n) alle Kategorien suchen, die sie enthalten. Mit einem Index auf (lft,rgt) könnte das als Index-Scan laufen, sonst ist es ein Table Scan. Hast Du einen Index?
Es ist allerdings auch nicht einfach, auf anderem Weg die Kategorien der zweiten Ebene zu finden. "Direkte Kinder suchen" ist eine Übung, mit der sich Nested Sets schwer tun, weil sie auf Tiefensuche optimiert sind. Wenn du den Pfad finden willst, der von einem Knoten zu seinem Wurzelknoten des Kategorienbaums führt, dann kannst Du das mit einer ähnlichen Query wie oben machen:
~~~sql
SELECT id, name
FROM kategorien
WHERE lft < :leafLeft AND rgt > :leafRight
ORDER NY lft
~~~
Deine Query von oben führt diese Pfadsuche für JEDE Kategorie aus und wählt die mit einer Pfadlänge von 2. Das ist sehr langsam.
Also – wie immer stellt sich die Frage nach dem EIGENTLICHEN Problem. Willst Du direkte Kindknoten finden? Willst Du die Knoten der zweiten Ebene finden? Ich denke, diese beiden Übungen sind in einem SQL Statement kaum performant lösbar (es sei denn du hast rekursive Queries, aber die wolltest Du ja gerade vermeiden). Es könnte helfen, wenn Du außer den Nested Set Intervallgrenzen noch an jeder Kategorie die ID der Eltern-Kategorie speicherst, dann kannst Du für eine Kind-Abfrage darüber gehen und hast sozusagen beide Welten vereint.
In einem in Wikipedia verlinkten [Text zu Nested Sets](http://www.php-resource.de/tutorials/tutorial,21,Das-Nested-Sets-Modell---Baeume-mit-SQL,1.htm) habe ich übrigens noch den Hinweis gefunden, dass es ineffizient ist, die Tabelle als ein einziges Nested Set aufzubauen. Bei Updates muss man dann sehr viel ändern. Statt dessen wurde dort vorgeschlagen, an jedem Knoten noch eine sogenannte Root-ID zu speichern und allen Kindern dieses Knotens diese Root-ID mitzugeben. Bei 20 Kategorien auf Top-Level hättest Du dann nicht ein Nested Set, sondern 20.
D.h. die Optimierung besteht darin, pro Zeile fünf Verwaltungsinformationen zu führen:
- ID
- RootID
- ParentID
- Lft
- Rgt
Und je nach Aktion nutzt du die sinnvollste Kombi davon.
_Rolf_
--
sumpsi - posui - clusi
hunderte Kategorien Abspeichern und ausgeben
bearbeitet von Rolf BHallo Bernd. Oder bist Du Michael?
verstehe ich das richtig? Die Query zählt für jede Kategorie, in wievielen Ober-Ebenen sie enthalten ist (wobei sie sich selbst mitzählt; X BETWEEN A AND B ist ein A <= X <= B Vergleich), und filtert dann die, wo der Zähler den Wert 2 annimmt. Du würdest hier also die Kategorien der zweiten Ebene bestimmen.
Allerdings ist dieses Statement unglaublich komplex. Der Server muss hier pro Kategorie (Zeile aus n) alle Kategorien suchen, die sie enthalten. Mit einem Index auf (lft,rgt) könnte das als Index-Scan laufen, sonst ist es ein Table Scan. Hast Du einen Index?
Es ist allerdings auch nicht einfach, auf anderem Weg die Kategorien der zweiten Ebene zu finden. "Direkte Kinder suchen" ist eine Übung, mit der sich Nested Sets schwer tun, weil sie auf Tiefensuche optimiert sind. Wenn du den Pfad finden willst, der von einem Knoten zu seinem Wurzelknoten des Kategorienbaums führt, dann kannst Du das mit einer ähnlichen Query wie oben machen:
~~~sql
SELECT id, name
FROM kategorien
WHERE lft < :leafLeft AND rgt > :leafRight
ORDER NY lft
~~~
Deine Query von oben führt diese Pfadsuche für JEDE Kategorie aus und wählt die mit einer Pfadlänge von 2. Das ist sehr langsam.
Also – wie immer stellt sich die Frage nach dem EIGENTLICHEN Problem. Willst Du direkte Kindknoten finden? Willst Du die Knoten der zweiten Ebene finden? Ich denke, diese beiden Übungen sind in einem SQL Statement kaum performant lösbar (es sei denn du hast rekursive Queries, aber die wolltest Du ja gerade vermeiden). Es könnte helfen, wenn Du außer den Nested Set Intervallgrenzen noch an jeder Kategorie die ID der Eltern-Kategorie speicherst, dann kannst Du für eine Kind-Abfrage darüber gehen und hast sozusagen beide Welten vereint.
In einem in Wikipedia verlinkten [Text zu Nested Sets](http://www.php-resource.de/tutorials/tutorial,21,Das-Nested-Sets-Modell---Baeume-mit-SQL,1.htm) habe ich übrigens noch den Hinweis gefunden, dass es ineffizient ist, die Tabelle als ein einziges Nested Set aufzubauen. Bei Updates muss man dann sehr viel ändern. Statt dessen wurde dort vorgeschlagen, an jedem Knoten noch eine sogenannte Root-ID zu speichern und allen Kindern dieses Knotens diese Root-ID mitzugeben. Bei 20 Kategorien auf Top-Level hättest Du dann nicht ein Nested Set, sondern 20.
D.h. die Optimierung besteht darin, Zeile fünf Verwaltungsinformationen zu führen:
- ID
- RootID
- ParentID
- Lft
- Rgt
Und je nach Aktion nutzt du die sinnvollste Kombi davon.
_Rolf_
--
sumpsi - posui - clusi
hunderte Kategorien Abspeichern und ausgeben
bearbeitet von Rolf BHallo Bernd. Oder bist Du Michael?
verstehe ich das richtig? Die Query zählt für jede Kategorie, in wievielen Ober-Ebenen sie enthalten ist (wobei sie sich selbst mitzählt; X BETWEEN A AND B ist ein A <= X <= B Vergleich), und filtert dann die, wo der Zähler den Wert 2 annimmt. Du würdest hier also die Kategorien der zweiten Ebene bestimmen.
Allerdings ist dieses Statement unglaublich komplex. Der Server muss hier pro Kategorie (Zeile aus n) alle Kategorien suchen, die sie enthalten. Mit einem Index auf (lft,rgt) könnte das als Index-Scan laufen, sonst ist es ein Table Scan. Hast Du einen Index?
Es ist allerdings auch nicht einfach, auf anderem Weg die Kategorien der zweiten Ebene zu finden. "Direkte Kinder suchen" ist eine Übung, mit der sich Nested Sets schwer tun, weil sie auf Tiefensuche optimiert sind. Wenn du den Pfad finden willst, der von einem Blatt-Element zum Wurzelknoten Kategorienbaums führt, dann kannst Du das mit einer ähnlichen Query wie oben machen:
~~~sql
SELECT id, name
FROM kategorien
WHERE lft < :leafLeft AND rgt > :leafRight
ORDER NY lft
~~~
Deine Query von oben führt diese Pfadsuche für JEDE Kategorie aus und wählt die mit einer Pfadlänge von 2. Das ist sehr langsam.
Also – wie immer stellt sich die Frage nach dem EIGENTLICHEN Problem. Willst Du direkte Kindknoten finden? Willst Du die Knoten der zweiten Ebene finden? Ich denke, diese beiden Übungen sind in einem SQL Statement kaum performant lösbar (es sei denn du hast rekursive Queries, aber die wolltest Du ja gerade vermeiden). Es könnte helfen, wenn Du außer den Nested Set Intervallgrenzen noch an jeder Kategorie die ID der Eltern-Kategorie speicherst, dann kannst Du für eine Kind-Abfrage darüber gehen und hast sozusagen beide Welten vereint.
In einem in Wikipedia verlinkten [Text zu Nested Sets](http://www.php-resource.de/tutorials/tutorial,21,Das-Nested-Sets-Modell---Baeume-mit-SQL,1.htm) habe ich übrigens noch den Hinweis gefunden, dass es ineffizient ist, die Tabelle als ein einziges Nested Set aufzubauen. Bei Updates muss man dann sehr viel ändern. Statt dessen wurde dort vorgeschlagen, an jedem Knoten noch eine sogenannte Root-ID zu speichern und allen Kindern dieses Knotens diese Root-ID mitzugeben. Bei 20 Kategorien auf Top-Level hättest Du dann nicht ein Nested Set, sondern 20.
D.h. Du hast pro Kategorie fünf Verwaltungsinformationen:
- ID
- RootID
- ParentID
- Lft
- Rgt
Und je nach Aktion nutzt du die sinnvollste Variante davon.
_Rolf_
--
sumpsi - posui - clusi