7

この種のものは、前の質問から続いています。

Where句に応じたSQL Serverクエリのタイムアウト

where句に応じて、クエリの実行が非常に遅くなります。CTEを使用してそのクエリを書き直し、問題をうまく回避しましたが、答えが見つかりませんでした。

別の同様のクエリが最近微調整されて別のフィールドが追加され、実行して 10,000 行を返すのに約 30 秒かかっていたパフォーマンスが突然低下し、10 時間以上かかるようになりました (最終的には同じ結果セットを返します)。今日、私はこれのトラブルシューティングを開始し、何か奇妙なことを発見しました.

私は常にdatetime値から日付のみを抽出する必要があるため、ロジックを関数に書きました:

CREATE FUNCTION [dbo].[cDate] ( @pInputDate    DATETIME )
RETURNS DATETIME
BEGIN
        RETURN CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)
END
GO

この新しい非効率的なクエリで、その関数をクエリのCAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)インラインに置き換えると、クエリの実行速度が最大 10 時間から 2 秒弱に低下することがわかりました。推定実行計画に違いは見られません。ちなみに、これは追加されたフィールドではありません。他のフィールドを追加すると、何らかの形で実行計画が変更され、上記の条件が増幅されたと思います。

私の質問は、これは正常ですか?上記のように、繰り返しのプロセスには関数を使用します。これは、何かを行うより効率的な方法を見つけた場合に、保守、記憶、および更新が容易になるためです。関数のパフォーマンスを向上させるために何かをする必要がありますか?

4

2 に答える 2

8

これを関数にカプセル化する必要がある場合は、「スカラー関数、インライン化、およびパフォーマンス: 退屈な投稿の面白いタイトル」を参照してください。

以下のように書き直します

CREATE FUNCTION dbo.cDate_Inline
(
    @pInputDate DATETIME
)
RETURNS TABLE
AS
    RETURN
    (
        SELECT DATEADD(day, DATEDIFF(Day, 0, @pInputDate), 0) AS [Date]
    )

次に、代わりに

SELECT *,
       [dbo].[cDate](modify_date) AS modified
FROM   sys.objects 

使用する

SELECT *,
       ca.Date AS modified
FROM   sys.objects
       CROSS APPLY dbo.cDate_Inline(modify_date) ca 

これは、クエリ オプティマイザーによってプランにインライン化されます。

于 2015-08-23T18:55:01.357 に答える
0

別の変数を追加して、宣言と戻りを行う可能性があります。これに対する思考プロセスは、入力の日時を変更するためのキャストと変換がボトルネックである可能性があります。これは当てはまらないかもしれませんが、多くの場合、スコープに新しい変数を設定する場合は、条件付けを行い、その変数にバインドしてそれを返すと、速度が向上する可能性があります。私は可能な限りスカラー関数を避ける傾向がありますが、より大きなデータ セットで使用し始めると、多くのパフォーマンスの問題が発生します。役立つかどうかはわかりませんが、入力とは無関係に新しいオブジェクトへの戻りを分離します。

CREATE FUNCTION [dbo].[cDate] ( @pInputDate    DATETIME )
RETURNS DATETIME
BEGIN
Declare @Output datetime  = CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)  -- 2008 method and newer

Declare @Output datetime;

Select @Output  = CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)  -- 2005 and prior method 


return @Output
END
GO
于 2012-12-19T19:19:09.667 に答える