Ich habe eine Tabelle, bestehend aus etwa 70.000 Zeilen und zwei Spalten (VARCHAR(16)
): id
und parent_id
.CTE vs T-SQL-Schleife zur Bestimmung der Tiefe der Objekthierarchie
Ich möchte eine 'Tiefe' Spalte füllen, die zeigt, wie weit ein bestimmter Datensatz vom 'root' Knoten entfernt ist.
z.B.
id,parent_id,depth
A,NULL,0
B,A,1
C,A,1
D,B,2
E,D,3
usw.
Ich begann durch eine Abfrage auf this answer auf eine ähnliche Frage basiert Schreiben:
WITH myCTE(id, depth) AS
(
SELECT id, 0 FROM objects where id = 'A'
UNION ALL
SELECT objects.id, depth + 1 FROM myCTE JOIN objects ON objects.parent_id = myCTE.id
)
SELECT id, depth FROM myCTE
Mit meinem Dataset (~ 80.000 Zeilen) die über fast zwei Stunden in Anspruch nimmt auszuführen !
schrieb ich dann meine Frage als eine Schleife und bekam weit bessere Leistung:
ALTER TABLE objects ADD depth INT NULL
DECLARE @counter int
DECLARE @total int
SET @counter = 0
UPDATE objects SET depth = 0 WHERE id = 'A'
SELECT @total = COUNT(*) FROM objects WHERE depth IS NULL
WHILE (@total > 0)
BEGIN
UPDATE objects SET depth = @counter + 1 WHERE parent_id IN (
SELECT id FROM objects WHERE depth = @counter
)
SELECT @total = COUNT(*) FROM objects WHERE depth IS NULL
SET @counter = @counter + 1
END
Der obige Code dauert nur ein paar Minuten (und es hat den Vorteil, die Ergebnisse zu der vorhandenen Tabelle hinzufügen)
Meine Frage ist, ob meine Ergebnisse typisch für die Verwendung eines CTE für dieses Problem sind oder ob ich etwas übersehen habe, das es erklären könnte? Indizes, vielleicht? (Ich habe gerade keine auf dem Tisch)
Wow. Nach meiner Erfahrung klingt das ziemlich untypisch. Müssen Ausführungspläne aktiviert werden, um einen Vergleich zwischen den beiden zu sehen? – Matt
@Matt - Es ist für sogar mäßig große Tabellen entscheidend, dass der rekursive Teil des CTE durch eine Indexsuche erfüllt werden kann oder [Leistung kann sich entsetzlich verschlechtern] (http://dba.stackexchange.com/q/15596/ 3690) –