性能调优很差在SQL Server中继承UDF。
最近我获得了一个新的SQL Server环境。我已经能够更快地制作不同的部分,因为我遇到了一个调用两个标量值函数的表值函数。问题是性能调优UDF是我非常陌生的东西之一,我想帮助我如何更快地实现这一点。
我理解标量值函数用于逐行处理。所以我正在寻找一种方法来加快速度。有人可以请帮助。以下是功能。
标量值函数1.添加它只是为了显示最新情况。
ALTER FUNCTION [dbo].[AgingFactorOverride]
(@Aging_Factor FLOAT,
@Company_ID INT,
@Survey_ID INT,
@Country_Code VARCHAR(50),
@Effective_Date DATETIME)
RETURNS FLOAT
WITH EXEC AS CALLER
AS
BEGIN
DECLARE @RetVal FLOAT
BEGIN
SELECT @RetVal = MAX(Aging_Factor)
FROM companysurveycountryaging csca
WHERE csca.company_id = @Company_ID
AND csca.Country_Code = @Country_Code
AND ISNULL(csca.survey_id, '') = CASE WHEN csca.survey_id IS NOT NULL
THEN @Survey_ID
ELSE ''
END
AND csca.effective_date = (SELECT MAX(cscaa.effective_date)
FROM companysurveycountryaging cscaa
WHERE cscaa.company_id = @Company_ID
AND cscaa.Country_Code = @Country_Code
AND ISNULL(cscaa.survey_id, '') = CASE WHEN cscaa.survey_id IS NOT NULL THEN @Survey_ID ELSE '' END
AND cscaa.effective_date <= @Effective_Date)
IF @RetVal IS NULL
BEGIN
SET @RetVal = @Aging_Factor
END
END
RETURN @RetVal
END
标量值函数2.
ALTER FUNCTION [dbo].[AgeData]
(@ValToAge float, @StartDate datetime, @EndDate datetime, @AgingFactor float)
RETURNS float
WITH EXEC AS CALLER
AS
BEGIN
Declare @RetVal float,@NumMonths float
if @AgingFactor is not NULL
Begin
Set @NumMonths=DateDiff(month,@StartDate,@EndDate);
Set @RetVal=@ValToAge*(1+(((@AgingFactor/12)*@NumMonths)/100));
End
else
set @RetVal=@ValToAge;
Return @RetVal
END
表值函数 - 以下是调用上述标量函数的查询示例。
Select
@Base25=ISNULL(dbo.AgeData(sd.base25,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
@Base50=ISNULL(dbo.AgeData(sd.base50,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
@Base75=ISNULL(dbo.AgeData(sd.base75,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
@BaseAVG=ISNULL(dbo.AgeData(sd.baseAVG,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
@TCC25=ISNULL(dbo.AgeData(sd.TCC25,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
@TCC50=ISNULL(dbo.AgeData(sd.TCC50,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
@TCC75=ISNULL(dbo.AgeData(sd.TCC75,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
@TCCAVG=ISNULL(dbo.AgeData(sd.TCCAVG,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
@Base10=ISNULL(dbo.AgeData(sd.Base10,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
@Base90=ISNULL(dbo.AgeData(sd.Base90,s.effective_Date,@Effective_Date,dbo.AgingFactorOverride(cs.aging_factor,@Company_ID,sd.Survey_ID,sd.Country_Code,@Effective_Date)),0),
from surveydata sd, surveys s,companysurveys cs
where cs.company_id=s.Company_ID and cs.survey_id=s.survey_id and s.survey_id=sd.survey_id
如果您还需要其他任何东西可以让这项工作更好,请告诉我。
答案 0 :(得分:0)
将标量函数更改为内联表值函数
GO
ALTER FUNCTION [dbo].[Agingfactoroverride] (@Aging_Factor FLOAT,
@Company_ID INT,
@Survey_ID INT,
@Country_Code VARCHAR(50),
@Effective_Date DATETIME)
RETURNS TABLE
WITH EXEC AS CALLER
AS
RETURN
(SELECT Isnull((SELECT Max(Aging_Factor)
FROM (SELECT Rnk = Dense_rank() OVER(ORDER BY effective_date DESC),
Aging_Factor
FROM companysurveycountryaging csca
WHERE csca.company_id = @Company_ID
AND csca.Country_Code = @Country_Code
AND (csca.survey_id = @Survey_ID or csca.survey_id is null)
AND csca.effective_date <= @Effective_Date) a
WHERE Rnk = 1), @Aging_Factor))
GO
ALTER FUNCTION [dbo].[Agedata] (@ValToAge FLOAT,
@StartDate DATETIME,
@EndDate DATETIME,
@AgingFactor FLOAT)
RETURNS TABLE
WITH EXEC AS CALLER
AS
RETURN
(SELECT CASE
WHEN @AgingFactor IS NOT NULL THEN @ValToAge * ( 1 + ( ( ( @AgingFactor / 12 ) * Datediff(month, @StartDate, @EndDate) ) / 100 ) )
ELSE @ValToAge
END);
使用outer apply
调用函数
SELECT Base25,
Base50,
Base75,
BaseAVG,
TCC25,
TCC50,
TCC75,
TCCAVG,
Base10,
Base90
FROM surveydata sd
INNER JOIN surveys s
ON s.survey_id = sd.survey_id
INNER JOIN companysurveys cs
ON cs.company_id = s.Company_ID
AND cs.survey_id = s.survey_id
OUTER apply (SELECT Base25 = Isnull(dbo.Agedata(sd.base25, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0),
Base50 = Isnull(dbo.Agedata(sd.base50, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0),
Base75 = Isnull(dbo.Agedata(sd.base75, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0),
BaseAVG = Isnull(dbo.Agedata(sd.baseAVG, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0),
TCC25 = Isnull(dbo.Agedata(sd.TCC25, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0),
TCC50 = Isnull(dbo.Agedata(sd.TCC50, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0),
TCC75 = Isnull(dbo.Agedata(sd.TCC75, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0),
TCCAVG = Isnull(dbo.Agedata(sd.TCCAVG, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0),
Base10 = Isnull(dbo.Agedata(sd.Base10, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0),
Base90 = Isnull(dbo.Agedata(sd.Base90, s.effective_Date, @Effective_Date, dbo.Agingfactoroverride(cs.aging_factor, @Company_ID, sd.Survey_ID, sd.Country_Code, @Effective_Date)), 0)) oa