2

次のように、DATEADD(DD,0, DATEDIFF(DD,0, @DATETIME)) を返す DATEONLY というスカラー値関数があります。

CREATE FUNCTION [DBO].[DATEONLY] ( @DATETIME DATETIME )
RETURNS DATETIME
BEGIN
    RETURN DATEADD(DD, 0, DATEDIFF(DD, 0, @DATETIME))
END

関数を使用してテーブルを選択すると、SQL Server プロファイラーは、直接 DATEADD(DD,0, DATEDIFF(DD,0, @DATETIME)) を使用した場合よりも高い RowCounts 数をカウントします。

私の Dropxbox の Public Folder には、私が話していることを再現できる script.sql があります。また、私の SQL Server Profiler から Trace.trc を見つけることもできます。

script.sql: https://www.dropbox.com/s/gwbh54jqas7fhhc/script.sql

trace.trc: https://www.dropbox.com/s/gwbh54jqas7fhhc/Trace.trc

簡単にするために、以下の RowCounts を見てください。

SELECT DATEADD(DD,0, DATEDIFF(DD,0, INCOMING)) AS DATA, COUNT(*) AS SOULS
FROM HELL
GROUP BY DATEADD(DD,0, DATEDIFF(DD,0, INCOMING))

行数 = 6

SELECT DBO.DATEONLY(INCOMING) AS DATA, COUNT(*) AS SOULS
FROM HELL
GROUP BY DBO.DATEONLY(INCOMING)

行数 = 32

私の実際のシナリオでは、これらの 32 行は数百万の RowCount になります。それらが同じものである場合、何が起こっているのですか?! アプリケーション全体を変更しないように最適化するにはどうすればよいですか?

どうもありがとう!

4

3 に答える 3

3

スカラー値のユーザー定義関数の実行は、SQL サーバーではあまり効率的ではありません。基本的に、テーブル内のすべての行である呼び出しごとに個別の実行呼び出しを行います。Adam Machanic は、スカラー udf の実行と、インライン テーブル値関数の実行がどのようにはるかに高速になるかについて説明している、このテーマに関する良い投稿をしています。

代わりに tvf 内のロジックを利用するようにクエリを書き直すことができます。これは、オプティマイザーが元の拡張クエリと同じクエリ プランを使用して実行し、実行中に同じ RowCounts=5 を示します。

CREATE FUNCTION [DBO].[DATEONLY2] ( @DATETIME DATETIME ) RETURNS TABLE
AS RETURN SELECT DATEADD(DD, 0, DATEDIFF(DD, 0, @DATETIME)) data

select data, count(*) as souls
from
(SELECT (select data from dbo.dateonly2(incoming)) data
FROM HELL) t
GROUP BY data
于 2011-07-12T19:36:29.843 に答える
1

これは、UDF が行ごとに毎回評価されるためです。あなたが経験していることはブログ投稿に記載されています: http://blogs.msdn.com/b/sqlserverfaq/archive/2009/10/06/performance-benefits-of-using-expression-over-user-defined-functions .aspx

于 2011-07-12T19:45:22.860 に答える
0

次のクエリを使用することをお勧めします

SELECT DATEADD(DD,0, DATEDIFF(DD,0, INCOMING)) AS DATA, COUNT(*) AS SOULS
FROM HELL
GROUP BY DATEADD(DD,0, DATEDIFF(DD,0, INCOMING))

受信列にインデックスを作成して、パフォーマンスの低下を回避できます。

于 2011-07-14T11:34:33.513 に答える