【发布时间】:2012-05-29 13:01:01
【问题描述】:
您好,感谢您的关注。
首先介绍一下这个问题的背景:
我有一个内联表函数,它在我开发的在 IIS7 上运行的 ASP.net 应用程序中无处不在。它是 30 个或更多存储过程的基础,所有过程通常最多在 200 毫秒内处理(足够快)。应用程序始终对所有数据库连接使用相同的连接字符串。函数本身运行时间最长约为 10 毫秒。
有时,对调用存储过程的页面的调用会在 15 秒后导致超时。此超时适用于该页面的所有用户,但其他也有使用此功能的存储过程的页面在此发生时仍然可以正常执行,这表明它是一个特定的存储过程有问题。但是,这发生在多个页面上,表明它是多个存储过程或函数本身。
使用不同的用户凭据从 Management Studio 会话中运行页面上的任何(或所有)存储过程的时间小于 200 毫秒,即使 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))
【问题讨论】:
标签: asp.net tsql user-defined-functions sql-execution-plan