【发布时间】:2018-08-02 04:44:15
【问题描述】:
我正在尝试优化以下递归 CTE,但没有运气。该表有 5079 条记录。
;WITH CTE_REC AS (
SELECT
ID
, ParentId
, ID as ChildId
, IsActive
FROM
#temp
UNION ALL
SELECT
C.ID
, C.ParentId
, H.ChildId
,H.IsActive
FROM
#temp AS C
INNER JOIN
CTE_REC H ON C.ID = H.ParentId
)
SELECT * FROM CTE_REC
上述查询的执行计划是:
IO 统计数据是:
(25441 row(s) affected)
Table 'Worktable'.
Scan count 20365, logical reads 193768, physical reads 0,
read-ahead reads 0, lob logical reads 0, lob physical reads 0,
lob read-ahead reads 0.
Table '#temp_______________________________________________________________________________________________________________000000001B2D'.
Scan count 2, logical reads 34, physical reads 0, read-ahead reads 17,
lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
我在临时表上创建了下面的索引。
CREATE INDEX IX_TEMP ON #Temp(Id,ParentId)
创建索引后,执行计划如下。
索引后的 IO 统计:
Table '#temp_______________________________________________________________________________________________________________000000001B2D'.
Scan count 20364, logical reads 40776, physical reads 0, read-ahead reads 0,
lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'.
Scan count 2, logical reads 142778, physical reads 0, read-ahead reads 0,
lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
仍然在索引之后有高扫描计数和逻辑读取。 CTE 返回 25411 行,我没有发现 CPU 时间有任何差异,即 400 毫秒有/无索引。
【问题讨论】:
-
你应该减少你的锚的行数。添加
WHERE ParentId IS NOT NULL可能是一个不错的选择,但这实际上取决于您的数据和您的需求。 -
为什么不使用
hierarchyid而不是递归? -
我不知道hierarchyid。你能给我任何关于hierarchyid的链接吗?
-
您的查询似乎是错误的。非常高的 Cardianility 估计。您应该改进您的 Anchor 和递归两者。
-
奇数格式。
标签: sql sql-server tsql sql-server-2012 query-performance