Frage

Dies ist ein Followup auf:
MySQL - Ist es möglich, alle zu bekommen Unterelemente in einer Hierarchie?

Ich habe eine beliebige eingehende Adjazenzliste Modell Tabelle (I am Punkt bin, dass ich kann wandelt es in ein Nested Sets .

las ich die MySQL-Daten, wie ein Nested Sets zu verwenden, obwohl es schien immer zu bekommen komplex und sehr komplexe Basisfunktionen zu tun, wie das Einfügen, Aktualisieren und Löschen.

Ein weiterer Blog zeigt, wie ein Trigger-System zu verwenden, mit dem Adjazenzliste Modell eine Tabelle der Vorfahren zu halten, dass jedes Objekt seiner Vorfahren beziehen.


Im Moment muss ich in der Lage, eine Liste aller Kinder eines gegebenen Knotens zurückzukehren, um sie zu ändern oder zu löschen. Diese hierarchische Struktur wird nicht die ganze Zeit ändert einmal erstellt, aber es wird eine Masse Menge der hierarchischen Strukturen sein.

Die drei Methoden, die ich sehen sind:

  1. Erstellt eine gespeicherte Prozedur , die eine rekursive Abfrage tun würde, dass die Renditen für alle Kinder.

  2. Convert to Nested Sets , die in die Komplexität bekommen erfordern würde und möglicherweise eine gespeicherte Prozedur erstellen, hinzufügen, bearbeiten und löschen, dass.

  3. Erstellen der Vorfahr Tabelle oben beschrieben auf Einfügen / Löschen Trigger alle Daten verarbeiten.

Wenn es andere Methoden Ich bin nicht zu erforschen, lass es mich wissen und ich werde diese Liste aktualisieren.

War es hilfreich?

Lösung

Quassnoi hat einige Performance-Tests auf dem verschachtelten Sätze Modell laufen und das Adjazenzliste Modell und dokumentierte die Ergebnisse und Empfehlungen in seine Blog-Post Adjazenzliste vs. verschachtelte Sätze: MySQL . Die Zusammenfassung ist:

  • Verschachtelte Sätze schneller zum Abrufen aller untergeordneten Knoten oder alle übergeordneten Knoten.
  • Verschachtelte Sätze ist eine schlechte Idee, wenn Sie häufig die Tabelle aktualisieren müssen.

Dies ist die Schlussfolgerung aus seinem Artikel:

  

In MySQL, das verschachtelten Sätzen Modell bevorzugt werden soll, wenn die Aktualisierungen die hierarhical Struktur sind selten und es ist erschwinglich die Tabelle für die Dauer eines Updates zu sperren (die Minuten auf einem langen Tisch nehmen kann).

     

Dies impliziert die Erstellung der Tabelle MyISAM Speicher-Engine verwendet, wodurch der Begrenzungskasten eines Geometrietyp, wie oben beschrieben, Indexieren mit einem räumlichen Index und persistierende den Pegel in der Tabelle.

     

Wenn der Updates auf die Tabelle häufig ist oder es ist inaffordable die Tabelle für einen langen Zeitraum durch eine Aktualisierung implizierte zu sperren, dann ist das Adjazenzliste Modell verwendet werden soll, die hierarchischen Daten zu speichern.

     

Dies erfordert eine Funktion Erstellen der Tabelle abzufragen.

Der Rest des Artikels zeigt, wie die Tabelle zu definieren, die Abfragen implementieren und bietet Performance-Messungen. Die Verwendung des räumlichen Index ist eine clevere Idee, um die Leistung des Nested Sets zu verbessern, die neu für Sie sein könnten.


Wenn Sie auch Ansätze ohne MySQL unter Berücksichtigung dann könnten Sie unter PostgreSQL , die eine andere ist freie und Open-Source-Datenbank. PostgreSQL unterstützt rekursive Abfragen in Form von rekursive allgemeine Tabellenausdrücke was macht die Abfrage hierarchische Daten einfacher als in MySQL und auch eine bessere Leistung. Quassnoi hat auch einen Artikel Adjazenzliste vs. verschachtelte geschrieben Sätze: PostgreSQL die Details, die zeigt,

.

Während wir über die Suche bei anderen Ansätzen sprechen, Oracle-Datenbank ist auch eine Erwähnung wert. Oracle hat auch eine CONNECT BY benutzerdefinierte Erweiterung, die sehr einfach und schnell hierarchische Daten machen abfragt. Quassnoi den Artikel Adjazenzliste vs. verschachtelte Sätze: Oracle wieder deckt die Leistungsdetails. Die Abfrage, die Sie brauchen, um alle Kinder zu bekommen, ist extrem einfach in diesem Fall:

SELECT *
FROM yourtable
START WITH id = 42
CONNECT BY parent = PRIOR id

Andere Tipps

Ich würde immer gehen mit der Nested Set für Scher Einfachheit und convienience. Ich schlage vor, immer diesem Artikel . Es zeigt excelent die Abfragen, die für die Arbeit mit solchen hierachrchical Daten benötigt werden. Der einzige Nachteil, den ich hier sehe ist, dass es langsamer mit Einsetzen bekommen kann / updateing neue Datensätze, wenn die hierachry ein gewisses Maß an Komplexität erreicht, aber das Lesen schneller als viele andere Lösungen, die ich gesehen hae.

Nur ein Beispiel aus dem Artikel geben über:

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS';

+-------------+----------------------+--------------+-------+
| lev1        | lev2                 | lev3         | lev4  |
+-------------+----------------------+--------------+-------+
| ELECTRONICS | TELEVISIONS          | TUBE         | NULL  |
| ELECTRONICS | TELEVISIONS          | LCD          | NULL  |
| ELECTRONICS | TELEVISIONS          | PLASMA       | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS  | FLASH |
| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS   | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL  |
+-------------+----------------------+--------------+-------+
6 rows in set (0.00 sec)

SQL weise, ich glaube nicht, dass jede schönere bekommen und einfacher;)

Ich habe keine Ahnung, auf die Stored Procedure Art und Weise. Aber da es Rekursion involces (in Ihrem Fall), ich weiß nicht, ob es schnell sein wird, mit vielen Ebenen in der Hierarchie. Ich nehme an, Sie können es versuchen.

Vielleicht sollten Sie dokumentenorientierte Datenbank wie MongoDB mit in Betracht ziehen. Es könnte Ihr Leben viel einfacher machen.

Wenn mit hierarchischen Datensätzen zu tun ich es am besten finden es im Auge mit Caching zu nähern. Einer der wichtigsten Vorteile für diese Art und Weise mit diesem Problem umzugehen, so ist es nicht erforderlich de-Normalisierung Sie Datenbank in etwas, das schwerer zu mutieren könnte.

Da die Speicherhaufen (memcache, redis usw.) Lookups sind viel schneller als SQL für einfache id -> data Auflösungen, würde ich sie verwenden, um eine Liste der IDs der direkten Kinder für jeden Knoten zwischenzuspeichern. Auf diese Weise können Sie ordentliche Leistung über einen rekursiven Algorithmus erhalten eine vollständige Liste für jeden Knoten zu bauen.

Zum Hinzufügen / einen neuen Knoten löschen, werden Sie nur seine direkte O(1) geordneten Cache müssen ungültig zu machen.

Wenn das nicht schnell genug ist, können Sie eine weitere Ebene der Cache auf eine Liste aller Kind eines Knotens an jedem Knoten hinzuzufügen. Damit dies funktioniert, mit einem anständig wandelbar Dataset, sollten Sie die Cache-Leistung (Verhältnis von Frisch- / Cache gespeicherten Hits) jedes Knotens aufnehmen und ein Toleranzniveau für festgelegt, wenn der Cache zu speichern. Dies kann auch in einem Heap-Speicher gespeichert werden, da es nicht-Vitaldaten.

Wenn Sie das erweiterte Caching-Modell verwenden, müssen Sie diese komplette Kinder-Listen Knoten beachten müssen für ungültig erklärt werden, wenn irgendetwas davon Kinder O(log n) geändert werden.

Wenn Sie Ihre Liste der Kinder haben ids Sie SQLs WHERE id IN( id1, id2, .... ) Syntax Abfrage für verwenden können, was Sie wollen.

Ich hatte einmal eine komplexe hierarchische beliebige Tiefe speichern Bill-of-Material-System in einem SQL-ähnlichen Datenbankmanagern, die für die Aufgabe nicht wirklich nach oben waren, und es endete zwingen chaotisch und knifflige indicies, Datendefinitionen, Abfragen, etc. Nachdem von Grund auf neu zu starten, die DB-Manager nur eine API zur Verfügung zu stellen für die Aufzeichnung liest und schreibt auf einfache indizierte Schlüssel und in externen Code berichten alle von der aktuellen Eingabe / Manipulation / tun, war das Endergebnis schneller zu implementieren zu verstehen, leichter und einfacher zu erhalten und zu verbessern. Die komplexeste Abfrage benötigt wurde im Wesentlichen SELECT A FROM B.

Also, statt der Einbettung Logik und Operationen innerhalb der Beschränkungen von MySQL, sollten Sie Code hämmern, um zu tun, was Sie wollen, und die sich auf MySQL nur für die untersten Ebene wird / Puts.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top