2017-02-14 7 views
3

私はクエリを高速化しようとしています。私は2つのスカラー値関数を1行につき2つのパラメーターをパラメーターとして実行する必要があります。ローごとに複数のスカラー関数を実行する最も効率的な方法

機能は、実行中の合計に基づいて計算を行い、そして2008年

は私のクエリのCTE部分がすべての行を取得するSQLサーバーでこれを行うには(私の知ること)簡単な方法はありません私は計算が必要で、各レベルごとに個別に実行する必要があります。ストアに対するクライアントの関係は1対多ですが、各ストアの計算に基づいてクライアントレベル(Store = 'All')で計算を取得することはできません。

私の最初の試みは、 'SELECT'ステートメントで関数呼び出しを行うことでしたが、それらは同期して実行される必要はないと読みました。以下の試みは、計算を非同期に実行しようとする際にテーブル値に変換しようとしていました。

私はOUTER APPLYが行く方法であるのか、これについてもっと効率的な方法があるのだろうと思っていました。

詳細情報が必要な場合はお知らせください。

DECLARE @StartTime INT 
SET @StartTime=20170101 

DECLARE @EndTime INT 
SET @EndTime=20170131 


;WITH IsAvgStores AS (
    SELECT 
     COALESCE(ParentClient,'All') AS ParentClient, 
     COALESCE(Client,'All') AS Client, 
     COALESCE(Store,'All') AS Store, 
     MAX(Answer_Threshold), 
     MAX(SL_Threshold) 
    FROM 
     client_hierarchy 
    WHERE 
     GETDATE() BETWEEN EFF_BEGIN_DATE AND EFF_END_DATE 
    GROUP BY ROLLUP(ParentClient,Client,Store) 
) 
SELECT I.ParentClient,I.Client,I.Store 
    ,SL.isAvg_SL_String 
    ,A.isAvg_ASA_String 
INTO #isAvgTemp 
FROM IsAvgStores I 
    OUTER APPLY (SELECT dbo.isAvg_S_B(ParentClient,Client,Store,Answer_Threshold,@StartTime,@EndTime) AS isAvg_SL_String 
       ) SL 
    OUTER APPLY (SELECT dbo.isAvg_A_B(ParentClient,Client,Store,SL_Threshold,@StartTime,@EndTime)  AS isAvg_ASA_String 
       ) A 
WHERE ParentClient<>'All' 

SELECT * 
FROM #isAvgTemp 
+0

ロールアップがどのように動作しているのかわかりません – Paparazzi

+0

@パパラッチあなたは正しいです、私はしきい値でMAX()を追加するのを忘れました。 – reidodorito

答えて

5

これはコメントには長すぎます。

outer applyは、スカラー値関数では冗長です。

SELECT I.ParentClient, I.Client, I.Store, 
     dbo.isAvg_S_B(ParentClient, Client, Store,A nswer_Threshold, @StartTime, @EndTime) AS isAvg_SL_String, 
     dbo.isAvg_A_B(ParentClient, Client, Store, SL_Threshold, @StartTime, @EndTime) as isAvg_ASA_String 
INTO #isAvgTemp 
FROM IsAvgStores I 
WHERE ParentClient <> 'All'; 

これはパフォーマンスにはまったく影響しません。クエリを単純化するだけです。

パフォーマンスを得るために、次の3つのオプションがあります。

    は、機能を削除するためのコードを書き直し
  • を。実行合計にはouter applyを使用してください。
  • コードを書き換えて関数を削除します。実行中の合計に対して再帰的なCTEを使用します。
  • コードを書き換えて関数を削除します。実行合計にカーソルを使用します。

これらはどれも最適ではありません。最初の2つは、個々のグループが小さい場合に機能します。この状況では、3番目のオプションが最良の選択肢になることができます。そして、私はカーソルをかなり忌み嫌うことに注意してください。

または、最適なオプション:SQL Serverのそれ以降のバージョンにアップグレードし、SQL Server 2012以降で提供される累積合計機能を使用します。

0

別のオプションは、スカラー値を返すinline table-valued functions(ITVF)にスカラー関数を変換することです。これはあなたのシナリオでは機能しないかもしれません。私の経験では、complex scalar functions generally perform poorly in SQL Server on larger result setsはRBARを実行しているためです。 ITVFを使用すると、SQL Serverはクエリをインライン化してクエリプランを最適化できます。

あなたが達成しようとしていた何のようになりますあなたのクエリOUTER APPLY

SELECT I.ParentClient, I.Client, I.Store, SL.isAvg_SL_String A.isAvg_ASA_String 
INTO #isAvgTemp 
FROM IsAvgStores I 
OUTER APPLY dbo.isAvg_S_B(ParentClient,Client,Store,Answer_Threshold,@StartTime,@EndTime)SL 
OUTER APPLY dbo.isAvg_A_B(ParentClient,Client,Store,SL_Threshold,@StartTime,@EndTime) A 
WHERE ParentClient <> 'All'; 

あなたの機能ではなく、単一の結果を使用してテーブルを返すだろうということで差異:

CREATE FUNCTION dbo.isAvg_S_B (...) 
RETURNS TABLE 
AS 
(
    SELECT ... AS 'isAvg_SL_String' 
    FROM ... 
); 

繰り返しますが、これは特定のシナリオでのパフォーマンスを向上させるかどうかはできませんが、コードを複製しないようにする価値はあると思います。

関連する問題