【发布时间】:2017-11-22 10:39:35
【问题描述】:
在我的表格视图中,我有 4 个要调用的标量函数。 例如:
CREATE view [SUMMARY]
AS
SELECT [Code] ,
...
dbo.[udf_REPORTTYPE](ts.LegTankSystemId,ReportingDate,analysis.[AnalysisTypeName]) as ReportingType ,
dbo.[udf_WATER](ts.SystemId,LastObsDate) as WaterReading,
case when analysis.LastObsDate is null then NULL else dbo.[udf_BJs_GENERAL](ts.LegTankSystemId,ISNULL(analysis.LastObsDate, ssd.ReportingDate)) end as [1Plus130_Reslut],
(CASE WHEN State ='NY' THEN dbo.[udf_NY](ts.SystemId,LastObsDate)
WHEN State ='CT' THEN dbo.[udf_CT] (ts.SystemId,LastObsDate)
END) AS State_SIR_Result
FROM LOBDW.SITE dimsite
LEFT JOIN [bjs].[udv_TANK] ts on dimsite.SiteId = ts.SiteId
...
在那些标量函数中,我读取相同的参数并进行不同的计算。
返回 400 行我的视图需要超过 1 分钟。这真的很糟糕。 如何提高这些标量函数的性能?如果两个函数都需要相同的数据,有没有办法从一个函数定义全局变量并在另一个函数中使用它?
例如函数;
CREATE FUNCTION [dbo].[udf_REPORTTYPE]
(
@TankSystemId int,
@TimeStamp datetime2(7),
@AnalysisTypeName varchar(10)
)
RETURNS varchar(10)
AS
BEGIN
DECLARE @ReportType varchar(10);
DECLARE @TimePeriod datetime2(7)
DECLARE @LatestAnalysisDate datetime2(7)
SELECT TOP 1 @TimePeriod = Date FROM udv_DailySiraData where TankSystemId=@TankSystemId ORDER BY Date DESC
SELECT TOP 1 @LatestAnalysisDate = LastObsDate FROM [udv_ANALYSES] where TankSystemId =@TankSystemId ORDER BY LastObsDate DESC
SET @ReportType=@AnalysisTypeName
IF ((@TimePeriod>=@TimeStamp) AND (@LatestAnalysisDate < @TimeStamp) AND @AnalysisTypeName IS NULL)
SET @ReportType = 'No Analysis Result';
IF ((@TimePeriod>=@TimeStamp) AND @AnalysisTypeName IS NULL)
SET @ReportType = 'Latest';
RETURN @ReportType;
END;
【问题讨论】:
-
您在视图中使用的表中是否定义了任何 I 索引?
-
@MarkKram 还没有索引。但是我尝试优化我的函数并查看性能,然后尝试进行索引。如果两个函数都需要相同的数据,有没有办法从一个函数定义全局变量并在另一个函数中使用它?
-
不要使用它们。考虑改用CTEs。
-
@codeConcussion 任何示例如何用 CTE 替换函数?
-
你的函数的问题是它们执行额外的查询,更糟糕的是,你每行执行另外 2-4 个函数(我想这也会执行额外的查询),并且由于函数被执行按 each 行,例如查询返回 100 多行,这意味着多 200-800 个 查询,这会大大降低性能。使用 CTE,您可以将所有逻辑放在一个查询中,然后加入该查询。另一种选择是使用
APPLY@Squirrel 的答案。
标签: sql sql-server