Sql server 2008 如何使函数在SQL中执行得更快?
我正在使用函数更新到一列,如Sql server 2008 如何使函数在SQL中执行得更快?,sql-server-2008,function,database-performance,Sql Server 2008,Function,Database Performance,我正在使用函数更新到一列,如 DetailedStatus = dbo.fn_GetProcessStageWiseStatus(PR.ProcessID, PR.ProcessRunID, getdate()) 在这一行中,500000条记录不断更新。就像一个环 因此,对少数记录使用此函数时,它的执行速度很快,但当它的500000条记录执行时,它会变得非常慢 如何使用多个记录使其执行更快 需要采取什么措施或使用什么拆分 功能: 结束 提前感谢。当您尝试更新500k行时,执行计划似乎有所更改
DetailedStatus = dbo.fn_GetProcessStageWiseStatus(PR.ProcessID, PR.ProcessRunID, getdate())
在这一行中,500000条记录不断更新。就像一个环
因此,对少数记录使用此函数时,它的执行速度很快,但当它的500000条记录执行时,它会变得非常慢
如何使用多个记录使其执行更快
需要采取什么措施或使用什么拆分
功能:
结束
提前感谢。当您尝试更新500k行时,执行计划似乎有所更改。 您可以尝试在from子句上设置forceseek提示,以强制使用seeks而不是scans 另外,虽然@iRowCount>@IlopCount应该替换为if exists,因为您基本上是在结果表上检查某些条件,并且需要尽早返回 我看到您在任何地方都使用nolock hint来允许脏读,您可以在调用存储过程中设置隔离级别read uncommitted并删除所有这些;或者考虑更改数据库以设置Read TypReType快照以避免锁。
顺便说一句,SQL Server中的标量函数调用非常昂贵,因此,如果在调用函数的循环中发生了大量更新/选择,则必须尽量避免使用函数。向我们展示该函数的功能!给我们看看代码!你能检查编辑过的问题而不是函数吗?你建议使用什么样的函数?@Pink将所有代码都放在一个存储过程中;是的,这违反了干吻原则。从基于集合的操作的角度重新思考所有代码,目前您正在以行为单位逐段执行所有操作。
CREATE FUNCTION [dbo].[fn_GetProcessStageWiseStatus]
(
@ProcessID INT
,@ProcessRunID INT
,@SearchDate SMALLDATETIME
)
RETURNS VARCHAR(100)
AS
BEGIN
DECLARE
@iLoopCount SMALLINT
,@iRowCount SMALLINT
,@StepProgress VARCHAR(100)
,@StepCount SMALLINT
IF EXISTS(
SELECT TOP 1 1
FROM dbo.Step S WITH(NOLOCK)
JOIN dbo.vw_FileGroup FG
ON S.FileConfigGroupID = FG.FileConfigGroupID
WHERE S.ProcessID = @ProcessID
AND S.Active = 1
AND FG.FileConfigGroupActive = 1
AND FG.Direction = 'Inbound'
)
BEGIN
SET @StepProgress = 'Not Received'
END
ELSE
BEGIN
SET @StepProgress = 'Not Started'
END
DECLARE @StepRunDetailsTable TABLE
(
KeyNo INT IDENTITY(1,1)
,StepID INT
,StepStartTime SMALLDATETIME
,StepEndTime SMALLDATETIME
,SourceEnv VARCHAR(100)
,DestEnv VARCHAR(100)
)
INSERT INTO @StepRunDetailsTable
SELECT
S.StepID
,MAX(isnull(SR.StepStartTime, '06/06/2079'))
,MAX(isnull(SR.StepEndTime, '06/06/2079'))
,isnull(SENV.EnvironmentName, '')
,isnull(DENV.EnvironmentName, '')
FROM dbo.ProcessRun PR WITH(NOLOCK)
JOIN dbo.StepRun SR WITH(NOLOCK)
ON SR.ProcessRunID = PR.ProcessRunID
JOIN dbo.vw_StepHierarchy SH
ON SR.StepID = SH.StepID
AND SH.Active = 1
JOIN dbo.Step S WITH(NOLOCK)
ON SH.StepID = S.StepID
JOIN dbo.WorkFlow WF WITH(NOLOCK)
ON S.WorkFlowID = WF.WorkFlowID
AND WF.Active = 1
JOIN dbo.Environment SENV WITH(NOLOCK)
ON SENV.EnvironmentID = WF.SourceEnvironmentID
AND SENV.Active = 1
JOIN dbo.Environment DENV WITH(NOLOCK)
ON DENV.EnvironmentID = WF.DestinationEnvironmentID
AND DENV.Active = 1
WHERE PR.ProcessRunID = @ProcessRunID
GROUP BY S.StepID, SENV.EnvironmentName, DENV.EnvironmentName, SH.StepOrder
ORDER BY SH.StepOrder ASC
SELECT @StepCount = COUNT(*)
FROM dbo.ProcessRun PR WITH(NOLOCK)
JOIN dbo.Step S WITH(NOLOCK)
ON PR.ProcessID = S.ProcessID
AND PR.ProcessRunID = @ProcessRunID
AND S.Active = 1
SELECT @iRowCount = COUNT(DISTINCT StepID) FROM @StepRunDetailsTable
SET @iLoopCount = 0
WHILE (@iRowCount > @iLoopCount)
BEGIN
SET @iLoopCount = @iLoopCount + 1
SELECT
@StepProgress =
CASE
--WHEN @SearchDate BETWEEN StepStartTime AND StepEndTime
WHEN @SearchDate >= StepStartTime AND @SearchDate <= StepEndTime
THEN DestEnv + ' Load in Progress'
WHEN @SearchDate > StepEndTime AND @iLoopCount < @StepCount
THEN 'Waiting on next step - Loaded to ' + DestEnv
WHEN @SearchDate > StepEndTime AND @iLoopCount = @StepCount
THEN 'Completed'
WHEN @SearchDate < StepStartTime AND @iLoopCount = 1
THEN 'Load Not Started'
ELSE @StepProgress
END
FROM @StepRunDetailsTable
WHERE KeyNo = @iLoopCount
END
RETURN @StepProgress