緊急ではなく、注文ステータス= 1(出荷済み)のすべての注文をカウントしたいと思います。
これは、最適化するための非常に単純なクエリである必要があります。Ordersテーブルに単純なフィルター処理されたインデックスを配置して、このクエリをカバーし、定数時間/ O(1)操作にします。ただし、クエリプランを見ると、意味のないインデックススキャンを使用しているように見えます。理想的には、このクエリはインデックス内のアイテムの数を返すだけである必要があります。
表は次のようになります(本質を理解するために簡略化されています)。
CREATE TABLE [dbo].[Orders](
[Id] [int] IDENTITY(1,1) NOT NULL,
[IsUrgent] [bit] NOT NULL,
[Status] [tinyint] NOT NULL
CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED ( [Id] ASC )
このフィルタリングされたインデックスを作成しました:
CREATE INDEX IX_Orders_ShippedNonUrgent ON Orders(Id) WHERE IsUrgent = 0 AND Status = 1;
さて、私がこのクエリを行うとき:
SELECT COUNT(*) FROM Orders WHERE IsUrgent = 0 AND Status = 1
クエリプランはIX_Orders_ShippedNonUrgentを使用しているようですが、インデックススキャンを実行し、Ordersの約150,000行で約200回の読み取りを実行しています。
フィルタリングされたインデックスが最新の状態に保たれていると仮定して、このクエリを常に一定時間で実行することは可能ですか?理想的には、インデックスのサイズを取得するために1回の読み取りのみを実行する必要があります。
このようにフィルタリングされていないインデックスに切り替えると、次のようになります。
CREATE INDEX IX_Orders_IsUrgentStatus ON Orders(IsUrgent, Status);
クエリプランはインデックスシークを使用しますが、それでもこの単純なクエリに答えるのに必要な数よりも多くの読み取りを実行します。
アップデート
私はこれを行うことができます
SELECT TOP 1 rows FROM sys.partitions p
INNER JOIN sys.indexes i
ON i.name = 'IX_Orders_ShippedNonUrgent'
AND i.object_id = p.object_id
AND i.index_id = p.index_id
9回の読み取りで結果が得られますが、単純なCOUNT(*)クエリを使用する方がはるかに簡単で脆弱性の少ない方法があるはずです。