TSQL IVF导致ASP.net应用程序超时

时间:2012-05-29 13:01:02

标签: asp.net tsql user-defined-functions sql-execution-plan

嗨,谢谢你的关注。

首先是问题背景:

我有一个内联表函数,它在我开发的ASP.net应用程序中无处不在地使用,在IIS7上运行。它是30个或更多存储过程的基础,通常最多可以处理200毫秒(超过足够快)。应用程序始终对所有数据库连接使用相同的连接字符串。该函数本身运行最多约10毫秒。

有时调用调用使用该函数的存储过程的页面将导致15秒后超时。此超时适用于页面的所有用户,但是其他具有使用此功能的存储过程的页面在发生这种情况时仍能正常执行,这表明它是一个存在问题的特定存储过程。然而,这发生在多个页面上,表明它是多个存储过程或函数本身。

使用不同的用户凭据在管理工作室会话中运行页面上的任何(或所有)存储过程都是<200ms,即使Web应用程序发生超时也是如此。

在函数上运行sp_recompile将始终从任何登录凭据中“清除”超时。

因为这是应用程序的关键部分,所以sp_recompile会尽快运行,并且几乎没有时间进行调试。此外,我从来没有能够随意重建超时。

我曾尝试对内联表函数进行大量研究,并没有发现任何暗示这是他们的常见问题,因此应避免使用它们。

问题:

这些超时是否可能是由使用该功能引起的,还是保证它们是依赖它的存储过程的问题?换句话说,重构存储过程以使用视图或通过内联封装适当的逻辑可能有任何好处吗?

我的猜测是它只是存储过程,我可能会通过添加针对未知的优化,适当的选项重新编译或本地化参数来解决这个问题,但是老实说我更愿意找到适用的解决方案到底层函数,以便我可以在一个位置应用修复。

功能:

CREATE FUNCTION [dbo].[fn_ObjectIDs] (
    @DateFrom       AS DATETIME = NULL
    ,@DateTo        AS DATETIME = NULL
    ,@Region        AS INT = NULL
    ,@FamilyID      AS INT = NULL
    ,@ParentID      AS INT = NULL
    ,@ChildID       AS INT = NULL
) RETURNS TABLE AS
RETURN
    SELECT DISTINCT
        obj.ID       AS IDs
    FROM tblObjects obj WITH (NOLOCK)
    INNER JOIN tblFamily fam WITH (NOLOCK)
            ON obj.famID = fam.famID
        LEFT JOIN tblCountry cntry WITH (NOLOCK)
            ON (@Region IS NOT NULL) AND (fam.countryId = cntry.countryId)
        LEFT JOIN tblParent parent WITH (NOLOCK)
            ON (@ParentID IS NOT NULL) AND (obj.ID = parent.objectID)
        LEFT JOIN tblChild child WITH (NOLOCK)
            ON (@ChildID IS NOT NULL) AND (obj.ID = child.objectID)
    WHERE
        obj.Visible = 1
        AND obj.statusID IN (3,4,6,8)
        AND ((@DateFrom IS NULL) OR (obj.CreatedDate >= @DateFrom))
        AND ((@DateTo IS NULL) OR (obj.CreatedDate <= @DateTo))
        AND ((@Region IS NULL) OR (cntry.regionID = @Region))
        AND ((@FamilyID IS NULL) OR (obj.famID = @FamilyID))
        AND ((@ParentID IS NULL) OR (parent.parentID = @ParentID))
        AND ((@ChildID IS NULL) OR (child.childID = @ChildID))

1 个答案:

答案 0 :(得分:1)

暂时添加一些日志记录以验证实际导致超时问题的原因。您可以在应用程序中执行此操作,也可以执行存储过程本身。让程序在执行时将当前时间戳和用于调用过程的参数写入日志记录表。还要将日志记录添加到应用程序然后,如果存在导致问题的特定参数或者问题是否在程序中,您将能够确定何时发生特定超时。

一般来说,用户定义的函数不是一个好主意,但我的理解是表内联函数比其他函数更好。它增加了大量开销,优化器无法与UDF一起正常工作。