3

次のような基本的なテーブルがあります。

create table Orders
(
    ID INT IDENTITY(1,1) PRIMARY KEY,
    Company VARCHAR(3),
    ItemID INT,
    BoxID INT,
    OrderNum VARCHAR(5),
    Status VARCHAR(5),
    --about 10 more columns, varchars and ints and dates
)

かなりの数のデッドロックと速度低下が発生しているため、すべての SQL を最適化しようとしていますが、私はこの種の専門家ではありません。

いくつかのインデックスを作成しました:
ID (主キー) でクラスター化されます。
([ItemID])
の非クラスター化インデックス ([BoxID])
の非クラスター化インデックス ([Company],[OrderNum],[Status]
)の非クラスター化インデックス

しかし、私は結果に 100% 満足しているわけではありません。

SELECT * FROM Orders WHERE ItemID=100

インデックス シーク + キー ルックアップとネスト ループ (内部結合) を提供します。理由はわかりますが、それについて何かする必要があるかどうかはわかりません。彼らのキールックアップはバッチの 97% で、悪いようです!

使用されるすべてのクエリはテーブルのすべての列を引き戻しますが、インデックスにすべての列を含めるという考えは好きではありません。

[Company] フィールドのすべてをクエリするように変更を加えています。結果には複数の値が含まれてはならないため、すべてのクエリでこれが使用されます。したがって、それらはすべて変更されます。

SELECT * FROM Orders WHERE ItemID=100    --Old
SELECT * FROM Orders WHERE Company='a' and ItemID=100    --New

しかし、その実行計画は、会社を含めないのとまったく同じです (これには驚きました!)。

  • 上記の 2 つの実行計画が同じなのはなぜですか? (現在、[会社] に関するインデックスはありません)

  • [Company] をすべてのインデックスに追加すると、0 が実行計画と異なるように見えるので、追加する価値はありますか?

  • 代わりに、[Company] に 1 つのインデックスを追加し、元のインデックスを保持する必要がありますか? -しかし、それはすべてのクエリに2つのシークがあることを意味しますか?

  • キー検索を回避するために、インデックスに他のすべての列を「含める」価値はありますか? (インデックスを1トン大きくしますが、潜在的に高速化しますか?)すなわち

    CREATE NONCLUSTERED INDEX [IX_Orders_MyIndex] ON [Orders]
    ( [Company] ASC, [OrderNum] ASC, [Status] ASC )
    INCLUDE ([ID],[ItemID],[BoxID],
    [Column5],[Column6],[Column7],[Column8],[Column9],[Column10],etc)
    

4 つまたは 5 つのインデックスでそれを行うと、面倒に思えます。

基本的に、かなり頻繁に実行される 4 ~ 5 個のクエリ (一部の選択と更新) があるため、できるだけ効率的にしたいと考えています。すべてのクエリは [company] フィールドと、少なくとも 1 つのその他のフィールドを使用します。どうすればいいですか。

どんな助けでも感謝します:)

4

1 に答える 1

3

実行計画では、ルックアップがバッチの 97% を占めると言っています。

この場合、インデックスのシークは非常に高速であり、実行する操作がそれほど多くないため、何の意味もありません。

そのルックアップは、実際には、指定したインデックスに基づいて読み取ったレコードです。

上記の 2 つの実行計画が同じなのはなぜですか? (現在、[会社] に関するインデックスはありません)

Non-Clustered index on ([Company],[OrderNum],[Status])

このインデックスは、、およびwhere 句に表示される場合Companyにのみ考慮されます。OrderNumStatus

連結されたインデックスは、この 0000000000000 のようなキーを生成します。これだけを渡すcompanyと、他の値にワイルドカードを使用する必要がある不完全なキーが作成されます。

これは次のようになります。key like 'XXX%'このロジックでは、時間のかかるインデックス スキャンが必要になります。

ItemIDオプティマイザーは、最初にインデックスから行をシークし、次にこれらをスキャンして必要な会社と一致させることが望ましいと判断します。

[Company] をすべてのインデックスに追加すると、0 が実行計画と異なるように見えるので、追加する価値はありますか?

Companyすべてのインデックスに追加するのではなく、インデックスを持つことを検討する必要があります。複合インデックスは、入れ子になったループの数を減らすことで処理を高速化できますが、その場合は十分に検討する必要があります。

このようなインデックスに追加するフィールドの順序は非常に重要です。より良いシークを可能にするために、一意性によって順序付けする必要があります。また、クエリで使用されない可能性のあるフィールドを追加しないでください。

代わりに、[Company] に 1 つのインデックスを追加し、元のインデックスを保持する必要がありますか? -しかし、それはすべてのクエリに2つのシークがあることを意味しますか?

複数のインデックス シークを使用することはそれほど悪いことではありません。通常、それらは並列化され、両方の結果のみが一致します。

キー検索を回避するために、インデックスに他のすべての列を「含める」価値はありますか? (インデックスを1トン大きくしますが、潜在的に高速化しますか?)

where 句で省略可能なフィールドがわずかしかない場合や、指定されたインデックスを使用しているときにそれらのフィールドのみを選択するクエリがある場合に価値があります。

最後のメモ

すべてのインデックスは等しくありません。文字列 (varchar) の比較は、数値 (整数、日時、バイトなど) の比較と同じではありません。

また、それらをきれいに保つことは非常に役立ちます.インデックスが断片化されている場合、パフォーマンスの向上という点ではほとんど役に立たなくなります.

于 2013-09-25T18:50:55.377 に答える