2017-11-22 5 views
2

私のテーブルビューでは、私は4スカラー関数を呼び出す必要があります。 例:SQLでスカラー関数のパフォーマンスを向上させるにはどうすればよいですか?

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 

...

私は同じパラメータを読み込み、異なる計算を行って、これらのスカラー関数で。

私の見解は、1分以上かかります400行を返すように。それは本当に悪いです。 これらのスカラー関数のパフォーマンスを改善することはできますか?ある関数からグローバル変数を定義し、両方の関数が同じデータを必要とする場合、その関数を別の関数で使用する方法はありますか?

例えば機能。

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 [email protected] ORDER BY Date DESC 
    SELECT TOP 1 @LatestAnalysisDate = LastObsDate FROM [udv_ANALYSES] where TankSystemId [email protected] ORDER BY LastObsDate DESC 

    SET @[email protected] 
    IF ((@TimePeriod>[email protected]) AND (@LatestAnalysisDate < @TimeStamp) AND @AnalysisTypeName IS NULL) 
     SET @ReportType = 'No Analysis Result'; 
    IF ((@TimePeriod>[email protected]) AND @AnalysisTypeName IS NULL) 
     SET @ReportType = 'Latest'; 

    RETURN @ReportType; 
END; 
+0

あなたはあなたのビューで使用しているテーブル9N定義された任意のIインデックスを持っていますか? –

+0

@MarkKramインデックスはまだありません。しかし、私は自分の関数を最適化しようとすると、パフォーマンスを参照してインデックスingをしようとします..ある関数からグローバル変数を定義し、両方の関数が同じデータを必要とする場合、別の関数で使用する方法はありますか? – Ratha

+1

使用しないでください。代わりに[CTEs](https://technet.microsoft.com/en-us/library/ms190766(v = sql.105).aspx)を使用してください。 – codeConcussion

答えて

3

あなたはOUTERへのあなたのUDFが適用変換することができ、この

SELECT [Code] , 
    ... 
    --dbo.[udf_REPORTTYPE](ts.LegTankSystemId,ReportingDate,analysis.[AnalysisTypeName]) as ReportingType , -- change from UDF to Outer Apply 
    RT.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 
    OUTER APPLY -- convert from udf_REPORTTYPE 
    (
     SELECT ReportingType = 
       CASE WHEN MAX(x.DATE) >= ssd.ReportingDate 
         AND  MAX(y.LastObsDate) < ssd.ReportingDate 
         AND  analysis.[AnalysisTypeName] iS NULL 
         THEN 'No Analysis Result' 
         WHEN MAX(x.DATE) >= ssd.ReportingDate 
         AND  analysis.[AnalysisTypeName] iS NULL 
         THEN 'Latest' 
         ELSE analysis.[AnalysisTypeName] 
         END 
     FROM udv_DailySiraData x 
      INNER JOIN udv_ANALYSES y ON x.TankSystemId = y.TankSystemId 
     WHERE x.TankSystemId = ts.LegTankSystemId 
    ) RT 
+0

ありがとうございます。これにより多くのパフォーマンスが向上します。この外側の適用がどのように性能を向上させるかを知ることができますか? – Ratha

+0

複数の関数を使用する場合は、このOuterApplyを複数回使用できますか?パフォーマンスはどのようになりますか?例:OUTER APPLY - udf_REPORTTYPEから変換する ( )RT OUTER APPLY - udf_WATERから変換する ( )WA – Ratha

+0

はい。あなたは1つ以上のアウターを使用することができます – Squirrel

1

私は正常に動作していると確信しているが、ここでは適用さOUTERへのCTEの代替は、だような何か...

WITH TimePeriods AS (
    SELECT 
     TankSystemId, 
     TimePeriod = MAX(Date) 
    FROM 
     udv_DailySiraData 
    GROUP BY 
     TankSystemId 
), AnalysisDates AS (
    SELECT 
     TankSystemId, 
     LatestAnalysisDate = MAX(LastObsDate) 
    FROM 
     udv_ANALYSES 
    GROUP BY 
     TankSystemId 
) 
SELECT 
    ... 
    ReportingType = 
     CASE 
      WHEN tp.TimePeriod >= ReportingDate AND ad.LatestAnalysisDate < ReportingDate AND analysis.AnalysisTypeName IS NULL THEN 'No Analysis Result' 
      WHEN tp.TimePeriod >= ReportingDate AND analysis.AnalysisTypeName IS NULL THEN 'Latest' 
      ELSE analysis.AnalysisTypeName 
     END, 
    ... 
FROM 
    LOBDW.SITE dimsite 
LEFT JOIN 
    bjs.udv_TANK ts 
    ON dimsite.SiteId = ts.SiteId 
LEFT JOIN 
    TimePeriods tp 
    ON ts.LegTankSystemId = tp.TankSystemId 
LEFT JOIN 
    AnalysisDates ad 
    ON ts.LegTankSystemId = tp.TankSystemId 
+0

ありがとう...私は試してみて、パフォーマンスを見てください。私はリスのように外側の適用を試みた、それはパフォーマンスを向上させます。 – Ratha

関連する問題