Wie können zwei Hierarchien effizient in SQL Server zusammengeführt werden?

8

Ich habe zwei Tabellen mit hierarchyid-Feldern, von denen eines eine Staging-Tabelle mit neuen Daten ist, die in das andere zusammengeführt werden müssen (dh eine Menge von Knoten, die zum Hauptbaum hinzugefügt werden müssen, von denen einige könnte schon da sein).

Zusätzlich zur hierarchyid-Spalte, die die Baumstruktur definiert (Eltern-Kind-Beziehungen). Jede Tabelle hat eine separate Spalte, die eine Knoten-ID enthält, die jeden Knoten eindeutig identifiziert. Das heißt, die Art und Weise zu bestimmen, ob ein Knoten aus der Staging-Tabelle bereits in der Haupttabelle ist, erfolgt über die Knoten-ID, nicht über die hierarchyid-Spalten.

Die Verarbeitung, die ausgeführt werden muss, würde wie folgt aussehen:

%Vor%

Wichtig ist, dass dieser Ansatz nur funktioniert, wenn der Baum in der Staging-Tabelle in der Reihenfolge erster Ordnung sortiert / durchlaufen wird - dies ist so, dass beim Auftreten von RS sichergestellt ist, dass sein Eltern-PS bereits eine entsprechende Zeile in der Haupttabelle.

Bisher ist die einzige Möglichkeit, dies im SQL-Server zu erreichen, ein Cursor über der Staging-Tabelle zu verwenden (der bereits sortiert ist) und eine gespeicherte Prozedur für jede Zeile aufzurufen, die im Wesentlichen genau das leistet, was oben beschrieben ist mit einem SELECT MAX (), um die höchste hierarchyid zu finden, die bereits als Kind von PM existiert, so dass das Kind eindeutig hinzugefügt werden kann.

Dies ist jedoch ein äußerst ineffizienter Ansatz und für meine Zwecke zu langsam. Gibt es einen besseren Weg?

Für den Hintergrund ist dies eine Machbarkeitsprüfung, die ich gerade mache. Ich muss herausfinden, ob ich diese Operation innerhalb von SQL Server schnell ausführen kann. Wenn es sich herausstellt, kann ich es nicht anders machen, außerhalb der Datenbank. Die Verschmelzung der Bäume ist inhärent (in gewissem Sinne ist ) die Problemdomäne, so dass die Daten anders strukturiert sind oder eine breitere Sichtweise haben und versuchen, diese Operation irgendwie zu vermeiden eine Option.

Aktualisieren

Wie gewünscht, hier ein konkretes Beispiel.

Die Tabellen "staging" und "main" haben beide die gleichen zwei Spalten:

%Vor%

Anfangsinhalt

main:

%Vor%

Staging:

%Vor%

Gewünschter Inhalt

main:

%Vor%

Beachten Sie, dass der Knoten in der Staging-Tabelle mit hierarchy_id / 1/1 / dem mit hiearchy_id / 1/2 / in der Zieltabelle entspricht (deshalb ist die node_id wichtig - kann nicht einfach hierarchy_id-Werte kopieren) . Beachten Sie auch, dass der neue Knoten mit node_id 6 als untergeordnetes Element des korrekten übergeordneten Elements hinzugefügt wird, das mit node_id 3, weshalb die hierarchy_id wichtig ist - sie definiert die Baumstruktur (Eltern / Kind-Beziehungen) für neue Knoten. Jede Lösung muss beide Aspekte berücksichtigen.

    
Tom 14.08.2011, 17:02
quelle

3 Antworten

3

Das Modellieren Ihrer Hierarchie auf diese Weise führt zu Problemen. Die Spalte hierarchy_id verletzt die erste normale Form, und der Prozess zum Zusammenführen wird anfällig für die Aktualisierung von Anomalien sein, wenn Sie keinen Serialisierungs- / Engpasszugriff durchführen.

Sie sollten eine Tabelle mit nur node_id und parent_id in Betracht ziehen, um zu sehen, wie sie Ihr Merge-Problem trivialisiert

%Vor%

Sie würden damit rekursive Abfragen verwenden und Sie wären überrascht, wie effizient die Ausführungspläne ausfallen. Wenn Sie die abgeflachte Hierarchie-Spalte haben müssen, können Sie wahrscheinlich eine indizierte Sicht mit einer rekursiven Abfrage erstellen.

    
gordy 14.08.2011, 18:33
quelle
3

Wir haben an einem Produkt gearbeitet, das eine ähnliche Lösung benötigt. Nach vielen Untersuchungen zu diesem und anderen Ansätzen haben wir festgestellt, dass die hierarchyID-Methode nicht für uns geeignet ist.

Also als direkte Antwort auf Ihre Frage: Es gibt keinen besseren Weg, dies mit diesem Ansatz zu tun.

Sehen Sie sich Modelle mit geschachtelten Mengen und Adjazenzlistenmodell .

Beides sind weitaus elegantere und effizientere Lösungen für diese spezielle Design-Herausforderung.

Bearbeiten: Als Nachdenklichkeit, falls Sie nicht mit SQL verheiratet sind, kann dieses Problem viel besser mit einer nicht-relationalen Datenbank gelöst werden. Wir konnten diesen Weg nicht gehen, da niemand genug Expertise im Entwerfen von nicht-relationalen Datenbanken hat, aber für den Fall, dass SQL optional ist, können Sie Ihren aktuellen Ansatz beispielsweise in MongoDB in einer viel netteren und effizienteren Weise verwenden.

    
Varun Vohra 14.08.2011 18:09
quelle
0

Hier ist eine Lösung, die die Zeilen von Quelle @S nach Ziel @T eine Ebene nach der anderen verschiebt. Um ein bisschen zu vereinfachen, habe ich einen Wurzelknoten hinzugefügt, um immer einen Elternknoten zu haben, der beim Erstellen der neuen HierarcyID verwendet wird.

Ich habe Hierarchie-ID nie benutzt, also könnte es durchaus effizientere Wege geben, dies zu tun, aber es sollte zumindest effizienter sein, als es eine Zeile zu einer Zeit zu tun.

%Vor%

Ergebnis:

%Vor%     
Mikael Eriksson 15.08.2011 04:24
quelle