3

バックグラウンド:

以前、私の会社では、ユーザー定義関数を使用して、ストアド プロシージャの where 句で一部のデータを html エンコードしていました。以下の例:

DECLARE @LName --HTML encoded last name as input parameter from user

SELECT * 
  FROM (SELECT LName
          FROM SomeView xtra
         WHERE (( @LName <> '' 
              AND dbo.EncodingFunction(dbo.DecodingFunction(xtra.LName)) = @LName) 
           OR @Lname=''))

わかりやすくするためにこれを単純化しました。

問題は、このクエリを含むストアド プロシージャが立て続けに 45 回呼び出された場合、62,000 レコードを含むテーブルでの平均パフォーマンスが約 85 秒だったことです。UDF を削除すると、パフォーマンスが 1 秒強に向上し、sproc を 45 回実行できました。

そのため、ビューによってアクセスされるテーブルに計算列を含むソリューションを検討し、決定しましたSomeView。計算列は、次のようにテーブル定義に書き込まれました。

[LNameComputedColumn] AS (dbo.EncodingFunction(dbo.DecodingFunction([LName])))

次に、テーブルを更新するプロセスを実行し、62,000 レコードすべての計算列を自動的に設定しました。次に、ストアド プロシージャ クエリを次のように変更しました。

DECLARE @LName --HTML encoded last name as input parameter from user

SELECT * FROM
      (SELECT LNameComputedColumn
      FROM SomeView xtra
      WHERE  (( @LName <> '' AND xtra.LNameComputedColumn=@LName) OR @Lname='')

そのストアド プロシージャを実行したところ、45 回の実行の平均実行時間は約 90 秒に増加しました。私の変更は実際に問題を悪化させました!

私は何を間違っていますか?パフォーマンスを向上させる方法はありますか?

ちなみに、現在 SQL Server 2000 を使用しており、間もなく 2008 R2 にアップグレードする予定ですが、すべてのコードは SQL Server 2000 で動作する必要があります。

4

2 に答える 2

8

計算済みを追加すると仮想列が作成されますが、選択された行ごとに実行時に計算されます。必要なのは、挿入時に計算され、テーブルに物理的に格納される、計算された永続列です。

[LNameComputedColumn] 
   AS (dbo.EncodingFunction(dbo.DecodingFunction([LName]))) PERSISTED
于 2012-04-05T01:30:48.707 に答える
3

Q: MS SQL 計算列がパフォーマンスを低下させています...

A: ホースホッケー ;)

 ... where @LName <> '' ...

Q: 「フル テーブル スキャン」と言えますか?

あなたの機能高価ではないと言っているのではありません。しかし、指を指す前に、より選択的な「where」句を作成する必要があります...

私見では...

提案:

  1. データをクエリします (関連するすべての「Lname」を最初に取得します)

  2. 結果に対して関数を実行します(選択した「Lnames」のみ-ビューまたはテーブル全体のすべての行ではないと思います)

  3. ストアド プロシージャで両方の操作 (フィルターを使用したクエリ、次に後処理) を実行します。

于 2012-04-05T01:08:18.597 に答える