有没有办法提高以下CTE查询的性能(@E
和@R
是实际系统中具有索引的表):
DECLARE @id bigint = 1
DECLARE @E TABLE
(
id bigint,
name varchar(50)
)
DECLARE @R TABLE
(
child_id bigint,
parent_id bigint
)
INSERT INTO @E SELECT 1, 'one'
INSERT INTO @E SELECT 2, 'two'
INSERT INTO @E SELECT 3, 'three'
INSERT INTO @E SELECT 4, 'four'
INSERT INTO @E SELECT 5, 'five'
INSERT INTO @E SELECT 6, 'six'
INSERT INTO @E SELECT 7, 'seven'
INSERT INTO @R SELECT 1, 2
INSERT INTO @R SELECT 1, 3
INSERT INTO @R SELECT 3, 4
INSERT INTO @R SELECT 5, 4
INSERT INTO @R SELECT 3, 6
INSERT INTO @R SELECT 7, 4
; WITH cte
(
child_id,
parent_id
)
AS (
SELECT * FROM @R R
WHERE R.child_id = @id
UNION ALL
SELECT R.* FROM @R R
INNER JOIN cte ON CTE.parent_id = R.child_id
)
SELECT * FROM @E E
WHERE e.id = @id
UNION ALL
SELECT P.* FROM @E E
INNER JOIN cte ON 1=1
INNER JOIN @E P ON P.id = cte.parent_id
WHERE e.id = @id
ORDER BY 1
预期结果:
id | name
1 | one
2 | two
3 | three
4 | four
6 | six
在真实世界的数据中,我将在 @R 中处理数百万行,在 @E 中处理约十万行。所以我想知道是否有任何办法可以挤出更多的性能。
编辑:为了澄清和总结到目前为止的情况,R 上有一个聚集 pk 索引,其中包含 child_id、parent_id,添加一个索引到 @r.parent_id 也将提高连接性能。
还有其他方式可以改进吗?在 CTE 之后使用 inner join 1=1 的部分是否有任何可以改进的地方,还是已经达到最佳状态了?是否有任何其他模式设计可以实现类似的父子映射并提高性能?
child_id
和parent_id
等 - 这将提高JOIN性能。 - marc_s(child_id)
和(parent_id)
上分别建立索引以加快JOIN性能。如果你按照这个顺序在(child_id, parent_id)
上建立复合索引,那么它可以用于child_id
单独使用-但不能用于parent_id
单独使用(而且它需要两者)。 - marc_s