我有一個由大約70,000行和兩列(均爲VARCHAR(16)
)組成的表格:id
和parent_id
。CTE與T-SQL循環用於確定對象層次結構的深度
我想填充一個「深度」列,顯示特定記錄離「根」節點的距離。
例如
id,parent_id,depth
A,NULL,0
B,A,1
C,A,1
D,B,2
E,D,3
等
我開始寫基於this answer查詢到類似的問題:
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
隨着我的數據集(〜8萬行)以上需要近兩個小時執行!
然後我寫我的查詢作爲一個循環,並得到了更好的性能:
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
上面的代碼只需要幾分鐘的時間(它有增加的結果到現有的表的利益)
我的問題是我的結果是使用CTE解決這個問題的典型結果,還是我忽略了一些可能解釋它的問題?索引,也許? (我現在沒有在桌面上)
哇。根據我的經驗,這聽起來很不典型。必須打開執行計劃才能看到兩者之間的比較? – Matt
@Matt - 對於即使是中等大小的表而言,CTE的遞歸部分能夠通過索引查找或[性能可降級嚴重]得到滿足,這一點至關重要(http://dba.stackexchange.com/q/15596/ 3690) –