0

次のクエリは、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 万件のレコードの「パラメーター」列に同じ値を取得しています。

4

2 に答える 2

6

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

于 2009-11-30T12:28:32.797 に答える
2

決定論的なスカラー関数でさえ、行ごとに少なくとも 1 回は評価されます。同じ決定論的スカラー関数が同じパラメーターを持つ同じ「行」で複数回発生する場合、その場合にのみ評価されると思います-たとえば、 aCASE WHEN fn_X(a, b, c) > 0 THEN fn_X(a, b, c) ELSE 0 ENDまたはそのようなもので。

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

同じシード値で RAND() を繰り返し呼び出すと、同じ結果が返されます。

1 つの接続で、指定されたシード値を使用して RAND() が呼び出されると、それ以降の RAND() のすべての呼び出しは、シードされた RAND() 呼び出しに基づいて結果を生成します。たとえば、次のクエリは常に同じ一連の数字を返します。

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

于 2009-11-30T13:46:09.783 に答える