4

しばらく前に、DBA の友人から特定の SQL クエリを高速化する方法を学びました。SQL Server がクエリをコンパイルする方法に関係があり、クエリ パスはインデックス付きの値を使用する必要があると彼が言及したことを覚えています。

これが私の元のクエリです(20秒かかります):

select Part.Id as PartId, Location.Id as LocationId
 FROM Part, PartEvent PartEventOuter, District, Location 
WHERE 
    PartEventOuter.EventType = '600'   AND PartEventOuter.AddressId = Location.AddressId  
    AND Part.DistrictId = District.Id   AND Part.PartTypeId = 15   
    AND District.SubRegionId = 11   AND PartEventOuter.PartId = Part.Id  
    AND PartEventOuter.EventDateTime <= '4/28/2009 4:30pm'   
    AND NOT EXISTS (
            SELECT PartEventInner.EventDateTime  
            FROM PartEvent PartEventInner
            WHERE PartEventInner.PartId = PartEventOuter.PartId
                AND PartEventInner.EventDateTime > PartEventOuter.EventDateTime 
                AND PartEventInner.EventDateTime  <= '4/30/2009 4:00pm')

「最適化された」クエリは次のとおりです (1 秒未満)。

select Part.Id as PartId, Location.Id as LocationId
 FROM Part, PartEvent PartEventOuter, District, Location 
WHERE 
    PartEventOuter.EventType = '600'   AND PartEventOuter.AddressId = Location.AddressId  
    AND Part.DistrictId = District.Id   AND Part.PartTypeId = 15   
    AND District.SubRegionId = 11   AND PartEventOuter.PartId = Part.Id  
    AND PartEventOuter.EventDateTime <= '4/28/2009 4:30pm'   
    AND NOT EXISTS (
            SELECT PartEventInner.EventDateTime  
            FROM PartEvent PartEventInner
            WHERE PartEventInner.PartId = PartEventOuter.PartId
                **AND EventType = EventType**
                AND PartEventInner.EventDateTime > PartEventOuter.EventDateTime 
                AND PartEventInner.EventDateTime  <= '4/30/2009 4:00pm')

これが非常に高速に実行される理由を詳しく説明できる人はいますか? 私はこれをよりよく理解しようとしています。

4

6 に答える 6

3

おそらく、 EventType = EventType なしでデカルト積を取得しているためです

ウィキペディアから: http://en.wikipedia.org/wiki/SQL

「[SQL] では、デカルト結合 (考えられるすべての組み合わせを結合する) を簡単に実行できます。その結果、WHERE 句のタイプが間違っていると、結果セットが「暴走」します。デカルト結合は、実際にはめったに使用されないため、明示的な CARTESIAN キーワードが必要になります。 (SQL 1992 では CROSS JOIN キーワードが導入され、デカルト結合が意図されていることをユーザーが明確にできるようになりましたが、述語のない省略形の「コンマ結合」は依然として許容される構文であり、同じ間違いを招きます。) "

実際には、最初のクエリで必要以上の行を処理しています。

http://www.fluffycat.com/SQL/Cartesian-Joins/

于 2009-08-06T22:02:44.877 に答える
0

この種のことは、現在よりもはるかに一般的でした。たとえば、Oracle 6 は、WHERE 句に制限を設定する順序に敏感でした。あなたが驚く理由は、SQL の構造に関係なく、DB エンジンが常に最適なアクセス パスを実行することを期待できるようになったからです。Oracle 6 & 7 (私はその後 MSSQL に切り替えました) には、クエリ プランの作成方法をデータベースに伝えるために使用できるヒント拡張機能もありました。

この特定のケースでは、実際のクエリ プランを見ずに決定的な答えを出すことは困難ですが、違いは、最初のクエリには使用されていないが、2 番目のクエリには使用されている EventType を使用する複合インデックスがあることだと思います。これは、最初のクエリで使用されていると予想されるという点で珍しいため、データベースの統計が古くなっている可能性があると思われます。

統計の再生成

もう一度試して、ここに結果を投稿してください。

于 2009-08-07T08:10:56.180 に答える
0

奇妙なことに、 と その中の両方EventTypeで定義されたインデックスがありEventDateTimeますか?

編集:
待って、EventTypeはnull可能な列ですか? 値が の場合、 *Column = Columnに評価されます。少なくともデフォルトの SQL Server 設定を使用します。FALSENULL

より安全な同等物はEventType IS NOT NULL. 速度的に同じ結果が得られることがわかりますか?


*: 私の T-SQL リファレンスには、TRUEANSI_NULLS設定してOFFに評価する必要があると書かれていますが、クエリ ウィンドウにはそうではないと書かれています。*今混乱* .
何か判決?TRUEFALSENULLまたはUNKNOWN? :) SQLの「バイナリ」ロジックが大好きです:(

于 2009-08-06T22:02:50.833 に答える
0

SQL Server は、このインデックスのすべての列がクエリにある場合にのみ、インデックス ルックアップを使用します。

于 2009-08-06T22:14:07.940 に答える
0

追加するすべての非インデックス列は、テーブル スキャンを実行します。WHERE 句の早い段階でクエリを絞り込むと、その後のスキャンが高速になります。したがって、インデックス スキャンを追加すると、テーブル スキャンはより少ないデータに対して実行されます。

于 2009-08-06T22:21:18.753 に答える