23

次の形式で、ビューに対して実行されている SQL Server でかなり複雑なクエリがあります。

SELECT *
   FROM myview, foo, bar 
   WHERE shared=1 AND [joins and other stuff]
   ORDER BY sortcode;

Sort上記のクエリ プランは、 final の直前の操作を示していますSELECT。これは私が期待するものです。一致するレコードは 35 件のみで、クエリにかかる時間は 2 秒未満です。

しかし、 を追加するTOP 30と、クエリに約 3 分かかります。使用SET ROWCOUNTは同じくらい遅いです。

クエリ プランを見ると、結合とフィルターのmyview 前に200 万件以上のレコードがすべて並べ替えられているように見えます。

この "並べ替え" は、クエリ プランで、インデックスのインデックス スキャンsortcode、メイン テーブルのクラスター化インデックス シーク、およびそれらの間の入れ子になったループとして表示されます。これらはすべて、結合とフィルターの前に行われます。

指定されていない場合のように、 SQL Server をSORT の直前 に強制するにはどうすればよいですか?TOPTOP

の構造が問題だとは思いませんが、念のためmyview、次のようなものです。

CREATE VIEW myview AS
   SELECT columns..., sortcode, 0 as shared FROM mytable
   UNION ALL
   SELECT columns..., sortcode, 1 as shared FROM [anotherdb].dbo.mytable

ローカルmytableには数千のレコードがありmytable、同じ MSSQL インスタンスの他のデータベースには数百万のレコードがあります。両方のテーブルには、それぞれの列にインデックスがあります。sortcode

4

1 に答える 1

12

そして、「オプティマイザーの裏をかこうとする (オプティマイザーが常に最善を知っているとは限らないため)」という不幸なゲームが始まります。

フィルタリング部分をサブクエリまたは CTE に入れてみることができます。

SELECT TOP 30 *
FROM
   (SELECT *
   FROM myview, foo, bar 
   WHERE shared=1 AND [joins and other stuff]) t
ORDER BY sortcode;

これは、最初に強制的にフィルタリングするのに十分な場合があります(ただし、オプティマイザはリリースごとに「賢く」なり、そのような悪ふざけを見抜くことができます)。または、このコードをUDFに入れる必要があるかもしれません。UDF を複数ステートメントのテーブル値関数として記述し、内部でフィルター処理を行い、その UDF をTOP x/ORDER BYでクエリすると、クエリの順序がかなり強制されます (SQL Server は現在、複数ステートメントの UDF を最適化できないため)。


もちろん、考えてみると、UDF を導入することは、私たちが実際に行っていることを隠す方法にすぎません。一時テーブルを作成し、1 つのクエリを使用して (WHERE フィルターに基づいて) データを入力し、次に別のクエリを使用して一時テーブルから を検索しますTOP x。テーブル。

于 2011-06-09T14:17:26.647 に答える