執行計劃不使用索引,它使用表掃描
我知道在使用索引或表掃描時,SQL Server 使用統計資訊來查看哪個更好。
我有一張有 2000 萬行的表。我在 (SnapshotKey, Measure) 和這個查詢上有一個索引:
select Measure, SnapshotKey, MeasureBand from t1 where Measure = 'FinanceFICOScore' group by Measure, SnapshotKey, MeasureBand
該查詢返回 500k 行。所以查詢只選擇了表中 2.5% 的行。
問題是為什麼 SQL Server 不使用我擁有的非聚集索引,而是使用表掃描?
統計數據已更新。
值得一提的是,查詢性能很好。
表掃描
強制索引
表/索引結構
CREATE TABLE [t1]( [SnapshotKey] [int] NOT NULL, [SnapshotDt] [date] NOT NULL, [Measure] [nvarchar](30) NOT NULL, [MeasureBand] [nvarchar](30) NOT NULL, -- and many more fields ) ON [PRIMARY]
桌上沒有PK,因為它是一個數據倉庫。
CREATE NONCLUSTERED INDEX [nci_SnapshotKeyMeasure] ON [t1] ( [SnapshotKey] ASC, [Measure] ASC )
如果您返回許多行和/或行非常寬,則索引查找可能不是最佳選擇。如果您的索引沒有覆蓋,查找可能會很昂貴。請參見此處的#2。
在您的場景中,查詢優化器估計執行 50,000 次單獨查找將比單次掃描更昂貴。優化器在掃描和查找之間的選擇(對查詢所需的列進行 RID 查找,但在非聚集索引中不存在)基於每個備選方案的估計成本。
優化器總是選擇它認為成本最低的替代方案。如果查看兩個執行計劃的根節點中的*Estimated Subtree Cost屬性,您會發現掃描計劃的估計成本低於查找計劃。*結果,優化器選擇了掃描。這基本上就是你問題的答案。
現在,優化器使用的成本模型基於不太可能與您的系統性能特徵相匹配的假設和“幻數”。特別是,模型中的一個假設是查詢開始執行時記憶體中沒有任何所需的數據或索引頁。另一個是順序 I/O(預期為掃描)比為 RID 查找假定的隨機 I/O 模式便宜。還有許多其他這樣的假設和警告,太多了,無法在這裡詳細介紹。
然而,作為一個整體的成本模型已被證明可以為大多數查詢、大多數數據庫模式、大多數硬體配置、大多數時間、任何地方生成總體上“足夠好”的計劃。如果你想一想,這是一個相當大的成就。
模型限制和其他因素有時意味著優化器選擇的計劃實際上根本“不夠好”。你報告說“性能很好”,所以這裡似乎不是這樣。