約70,000行と2列(両方VARCHAR(16)
)で構成されるテーブルがあります:id
とparent_id
。
特定のレコードが「ルート」ノードからどれだけ離れているかを示す「深さ」列にデータを入力したいと思います。
例えば
id,parent_id,depth
A,NULL,0
B,A,1
C,A,1
D,B,2
E,D,3
等
私は、同様の質問に対するこの回答に基づいてクエリを作成することから始めました。
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
私のデータセット(〜80,000行)では、上記の実行にはほぼ2時間かかります!
次に、クエリをループとして記述し、パフォーマンスを大幅に向上させました。
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を使用する典型的なものであるかどうか、またはそれを説明する可能性のある見落としているものがあるかどうかです。インデックス、多分?(私は今テーブルに何もありません)