2

古いレガシーシステムを書き直しています。という機能がありますcheckExisting()。古いシステムは、次のように MSSQL データベースからオブジェクトを抽出するためにクエリを使用していました (ADO DB を使用):

SELECT ObjectId, Name..... 
FROM tblRegisteredIncludes   
WHERE UPPER("Name") IN ('PROGA.H', 'PROGB.H'...............  list)

多くのテーブルがありますがtblRegisteredIncludes、SQL はテーブル名でグループ化され、オブジェクト名のリストで IN 句を使用しています。

これは、SQL Server が 1 回のスキャンですべてのオブジェクトを収集Nameし、テーブルの列にインデックスがあったため、適切に高速に実行されています。

しかし、新システムではWHERE条件が複雑になるため、同じSQLを使うことができません。また、ソース フィールドを使用しており、場合によっては条件内の他のフィールドも使用しています。多数の単一 SQL クエリがあります。

SELECT ObjectId, Name..... FROM tblRegisteredIncludes   
WHERE UPPER("Name") = 'PROGA.H' AND UPPER("Source") = "..."

SELECT ObjectId, Name..... FROM tblRegisteredIncludes   
WHERE UPPER("Name") = ('PROGB.H') AND UPPER("Source") = "..."

表の Name-IndextblRegisteredIncludesを の複合インデックスに置き換えました(Name,Source)

それでも、合計 SQL 実行は少し遅くなることが予想されますが、15 ~ 20% を超えることはありません。代わりに、はるかに遅くなり、時には最大 100% になります。UNION ALL を使用して、SQL を 1 つの大きな SQL クエリに結合しようとしました。

SELECT ObjectId, Name..... FROM tblRegisteredIncludes   
WHERE UPPER("Name") = 'PROGA.H' AND UPPER("Source") = "..."
UNION ALL
SELECT ObjectId, Name..... FROM tblRegisteredIncludes   
WHERE UPPER("Name") = ('PROGB.H') AND UPPER("Source") = "..."

結果のADO DBレコードセットを後で処理しますが、さらに遅くなります!

これらのクエリをより速く実行するための効率的な方法があるかどうかを知る必要がありますか? IN 句と名前のリストを使用する場合、以前のケースと同様のパフォーマンスを達成する必要があります。実行計画を提供できます。

4

2 に答える 2

3

このunion allバージョンでは、各サブクエリによってテーブルが個別にスキャンされます。

or条件を使用してすべての行を取り込む必要があります。

SELECT ObjectId, Name.....
FROM tblRegisteredIncludes   
WHERE (UPPER("Name") = 'PROGA.H' AND UPPER("Source") = "...") or
      (UPPER("Name") = ('PROGB.H') AND UPPER("Source") = "...") or
      . . .

Nameすべての比較がオンになっている状況がある場合はSource、CTE を使用してオンザフライでテーブルを作成することをお勧めします。

with toinclude as (
   select 'PROGA.H' as name, 'SOURCE' as source union all
   select . . .
)
select ri.ObjectId, ri.Name
from tblRegisteredIncludes join
     toinclude
     on ri.name = toinclude.name and ri.source = toinclude.source

実装またはフィールドがデフォルトの大文字と小文字を区別しない動作をオーバーライドしたことtoupper()を特に気にしない限り、 を省略できます。句で関数を使用すると、where通常、インデックスを使用できなくなります。

于 2013-03-21T13:10:19.080 に答える
0

あなたが説明したことから、テーブルには非常に多くの行があると思います。その場合、速度の問題を引き起こしているのはほぼ確実に UPPER です。これは、正しく設定されているように見えるインデックスを適切に使用できないことを意味します。保存されたデータは本当に大文字と小文字を区別しますか? - db 設定を確認してください。デフォルトでは通常そうではありません。この場合、UPPER を削除できます。

大文字と小文字が区別される場合、保存された名前の大文字と小文字が一致している場合でも、大文字を削除して、一貫した大文字/小文字の名前が何であれ、たとえば Name = 'ProgB.H' を使用できます。

于 2013-03-21T12:48:37.423 に答える