【问题标题】:Extremely slow Table-Valued-Function with recursive CTE inside内部带有递归 CTE 的极慢表值函数
【发布时间】: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


【解决方案1】:

如上所述,fiData 列上的索引解决了性能问题

【讨论】:

    猜你喜欢
    • 2022-01-01
    • 2011-07-03
    • 1970-01-01
    • 2015-08-12
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 2018-04-29
    • 2021-07-19
    相关资源
    最近更新 更多