1

私のシステムはかなり重い処理を行っており、より短い時間でより多くのテストを実行できるようにするために、パフォーマンスを攻撃してきました。

たとえば、500 万行で UDF を呼び出さなければならないケースがかなりあります (そして、それを回避する方法はほとんどないと思っていました)。

結局のところ、これを回避する方法があり、行の合計セットよりもやや小さい個別のパラメーターのセットで UDF が呼び出されると、パフォーマンスが大幅に向上します。

一連の入力を受け取り、複雑なロジックに基づいて結果を返す UDF を考えてみましょう。ただし、500 万行を超える一連の入力の場合、たとえば 100,000 の個別の入力しかないため、100,000 の個別の結果タプルしか生成されません (私の特定のケースは金利から複雑なコード割り当てまでさまざまですが、それらはすべて離散的です。この手法の基本的なポイントは、を実行することでトリックが機能するかどうかを簡単に判断できることですSELECT DISTINCT)。

私はこのようなことをすることでそれを見つけました:

INSERT INTO PreCalcs
SELECT param1
       ,param2
       ,dbo.udf_result(param1, param2) AS result
FROM (
    SELECT DISTINCT param1, param2 FROM big_table
)

PreCalcs が適切にインデックス化されている場合、それと次の組み合わせ:

SELECT big_table.param1
    ,big_table.param2
    ,PreCalcs.result
FROM big_table
INNER JOIN PreCalcs
    ON PreCalcs.param1 = big_table.param1
    AND PreCalcs.param2 = big_table.param2

パフォーマンスが大幅に向上します。どうやら、何かが決定論的だからといって、SQL Server が過去の呼び出しをキャッシュして再利用しているとは限りません。

注意しなければならない唯一のことは、NULL が許可されている場所です。その後、結合を慎重に修正する必要があります。

SELECT big_table.param1
    ,big_table.param2
    ,PreCalcs.result
FROM big_table
INNER JOIN PreCalcs
    ON (
        PreCalcs.param1 = big_table.param1
        OR COALESCE(PreCalcs.param1, big_table.param1) IS NULL
    )
    AND (
        PreCalcs.param2 = big_table.param2
        OR COALESCE(PreCalcs.param2, big_table.param2) IS NULL
    )

これが役に立てば幸いです。UDF を使用した同様のトリックや、パフォーマンスのためのクエリのリファクタリングは大歓迎です。

問題は、なぜこのような手動キャッシュが必要なのかということだと思います-関数が決定論的であることをサーバーが知っているのはそれではないでしょうか? そして、それが非常に大きな違いを生み、UDF が非常に高価である場合、なぜオプティマイザーは実行計画でそれを行わないのでしょうか?

4

2 に答える 2

4

はい、オプティマイザーは UDF を手動でメモ化しません。この方法で出力セットを折りたたむことができる場合、あなたのトリックは非常に優れています。

UDF のパラメーターが他のテーブルへのインデックスであり、UDF がそれらのテーブルから値を選択してスカラー結果を計算する場合、パフォーマンスを向上させることができるもう 1 つの手法は、スカラー UDF を、すべての結果値を選択するテーブル値 UDF として書き直すことです。潜在的なパラメーター。

UDF クエリの基になるテーブルが多くの挿入と更新の対象となり、関連するクエリが比較的複雑で、元の UDF を適用する必要のある行数が多い場合に、このアプローチを使用しました。この場合、テーブル値 UDF を 1 回実行するだけで、最適化されたセット指向のクエリとして実行できるため、パフォーマンスを大幅に向上させることができます。

于 2009-02-03T15:44:08.177 に答える
2

SQL Server は、500 万行内に 100,000 の個別の組み合わせがあることをどのように認識しますか?

PreCalcs テーブルを使用すると、元に戻す前に、500 万行ではなく 10 万行を超える udf を実行するだけです。

この有用な情報を推測できるオプティマイザーは存在しません。スカラー udf はブラック ボックスです。

より実用的な解決策として、udf 呼び出しを実行する計算済みの永続化された列を使用します。したがって、すべてのクエリで使用でき、インデックスを作成/含めることができます。

これは OLTP に適しているかもしれません... テーブルをクエリして、さまざまな方法でリアルタイムで取引の現金とポジションを取得するため、このアプローチは毎回 udf 数学のオーバーヘッドを回避するのに適しています。

于 2009-02-03T14:40:43.873 に答える