SQLで大きなパフォーマンスの違い(1時間から1分)が見つかりました。理由を説明できますか?

StackOverflow https://stackoverflow.com/questions/1819513

質問

次のクエリは、100万レコードの標準マシンでそれぞれ70分と1分かかります。考えられる理由は何ですか?

クエリ[01:10:00]

SELECT * 
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
    CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')        
        THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')        
        ELSE sys.fn_cdc_increment_lsn(0x00) END
    , sys.fn_cdc_get_max_lsn()
    , 'all with mask') 
WHERE __$operation <> 1

クエリの変更[00:01:10]

DECLARE @MinLSN binary(10)
DECLARE @MaxLSN binary(10)
SELECT @MaxLSN= sys.fn_cdc_get_max_lsn()
SELECT @MinLSN=CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')     
        THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')        
        ELSE sys.fn_cdc_increment_lsn(0x00) END

SELECT * 
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
        @MinLSN, @MaxLSN, 'all with mask') WHERE __$operation <> 1

[変更]

パラメータが各行で評価されるかどうかを確認するために、同様の関数を使用してシナリオを再作成しようとしました。

CREATE FUNCTION Fn_Test(@a decimal)RETURNS TABLE
AS
RETURN
(
    SELECT @a Parameter, Getdate() Dt, PartitionTest.*
    FROM PartitionTest
);

SELECT * FROM Fn_Test(RAND(DATEPART(s,GETDATE())))

しかし、38秒で100万件のレコードが処理された場合、「パラメータ」列に同じ値が表示されます。

役に立ちましたか?

解決

確定的なスカラー関数でも、行ごとに少なくとも1回評価されます。同じ「行」で同じ決定性スカラー関数が複数回発生する場合同じパラメータで、一度だけ評価されると信じています-例えば<コード> CASE WHEN fn_X(a、b、c)&gt;の場合0 THEN fn_X(a、b、c)ELSE 0 END またはそのようなもの。

RANDの問題は、再シードを続けるためだと思います:

  

RAND()の繰り返し呼び出し   同じシード値は同じを返します   結果。

     

1つの接続で、RAND()が   指定されたシード値で呼び出され、   RAND()の以降のすべての呼び出しは、   シードされたRAND()に基づく結果   コール。たとえば、次のクエリ   常に同じシーケンスを返します   数字の

私はあなたが示したようにスカラー関数の結果をキャッシュしました-スカラー関数の結果のテーブルを事前計算してそれらに結合するまでです。最終的には、スカラー関数を実行させるために何かをする必要があります。そうではなく、最良のオプションはCLRです-これらは明らかにSQL UDFよりも優れています。残念ながら、現在の環境では使用できません。

他のヒント

最初のクエリでは、 fn_cdc_increment_lsn および fn_cdc_get_min_lsn がすべての行に対して実行されます。 2番目の例では、1回だけです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top