次のような基本的なテーブルがあります。
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 つのその他のフィールドを使用します。どうすればいいですか。
どんな助けでも感謝します:)