【发布时间】:2010-10-15 14:58:56
【问题描述】:
我创建了一个 TVF,它返回一个包含来自递归 CTE here 的父记录的表。 效果很好,结果可以直接获得。现在我想获取子记录(它们与当前记录的 PK 具有相同的 FK)。 问题是获取给定 id 的 22 条子记录需要 1:10 分钟。 与寻找父记录的相反 TVF 相比,这为什么这么慢?
这是ITVF:
CREATE FUNCTION [dbo].[_nextClaimsByIdData] (
@idData INT
)
RETURNS TABLE AS
RETURN(
WITH NextClaims
AS(
SELECT 1 AS relationLevel, child.*
FROM tabData child
WHERE child.fiData = @idData
UNION ALL
SELECT relationLevel+1, parent.*
FROM NextClaims nextOne
INNER JOIN tabData parent ON parent.fiData = nextOne.idData
)
SELECT TOP 100 PERCENT * FROM NextClaims order by relationLevel
)
这是关系:
以下是示例查询的(正确)结果:
select relationLevel,idData,fiData from dbo._nextClaimsByIdData(30755592);
rl idData fiData
1 30073279 30755592
2 30765260 30073279
3 31942491 30765260
4 30895945 31942491
5 48045119 30895945
6 48342321 48045119
7 48342320 48342321
8 48308966 48342320
9 48308965 48308966
10 47044261 48308965
11 47044260 47044261
12 47253273 47044260
13 47253272 47253273
14 47279292 47253272
15 47279293 47279292
15 47494589 47279292
16 47494588 47494589
17 46051999 47494588
18 46373053 46051999
19 46083426 46373053
20 46099567 46083426
21 46600314 46099567
22 46595167 46600314
性能丢失的原因可能是在我的第一个 TVF(上面链接)中我正在寻找主键,而在这个 TVF 中我正在寻找(自引用)外键?如果是,我该如何优化我的表模式来加速查询?
更新:我发现这个性能问题的原因是fiData(表的主键上的外键列)上没有索引。经过创建和重组,结果立马就来了。
谢谢。
【问题讨论】:
-
不知道为什么会更慢
SELECT TOP 100 PERCENT * FROM NextClaims order by relationLevel肯定很臭,应该换成SELECT * FROM NextClaims。如果您想订购,则必须由调用代码完成。执行计划是什么样的? -
我想将顺序(以及复杂性)封装在这个函数中,这样调用者就不必知道内部顺序。但此外,这不能成为性能损失的原因。我会在星期一看看它;)
-
@Tim - 臭的原因是它不起作用。它将得到优化。要查看此内容,请尝试将其更改为
order by relationLevel DESC -
@Tim Schmelter - 尝试对视图应用排序绝对是代码异味。视图应该像表一样表示一组无序的行。此外,即使您应用了排序,它仍然不能保证输出顺序。 tinyurl.com/25aa3bx。也就是说,“但这是许多人不知道的部分——根据关系模型,针对表表达式的查询不能保证表示顺序,除非最外面的查询有表示 ORDER BY 子句。保证表示顺序仅在直接级别,而不是在代码的外部级别。”
-
@Tim Schmelter - 您示例中的 Order By 仅由 TOP 命令用于确定要返回的行。它不用于规定输出顺序,这是 Itzik Ben-Gan 在我提供的文章中抱怨的混乱。
标签: sql-server sql-server-2005 performance common-table-expression user-defined-functions