Sql-Server
由於“SELECT *”的聚集表掃描
我有一個
Records
包含 100 多列和非常多行的表,以及基於我的訪問路徑的 5 個欄位的非聚集索引:CREATE NONCLUSTERED INDEX [IX_Records_CustomerID] ON [dbo].[Records] ( [CustomerID] ASC, -- int [IsInvalid] ASC, -- int [IsProcessed] ASC, -- bit [IsRejected] ASC, -- bit [RecordName] ASC, -- varchar(12) ;
這5個欄位不包括主鍵
RecordID
,即聚集索引中的列。這是我表現不佳的查詢:
SELECT * FROM Records WHERE CustomerID IN (181, 283, 505)
執行計劃顯示它執行聚集索引掃描,我理解這是因為我選擇了索引中未包含的列。在 Management Studio 中,我將查詢更改為:
SELECT CustomerID, IsInvalid, IsProcessed, IsRejected, RecordName FROM Records WHERE CustomerID IN (181, 283, 505)
並且執行計劃顯示一個Index Seek,查詢執行時間從44秒下降到2秒。但是,我無法在應用程序中自由地
*
僅用我需要並已包含在我的索引中的列替換 。當我被鎖定時,有什麼辦法可以繞過聚集索引掃描
SELECT *
?
如果您需要輸出中未包含在索引中的列,則優化器必須做出選擇:
- 執行表/聚集索引掃描(因此所有列都在那裡)
- 執行查找,然後執行查找以檢索未涵蓋的列
它將選擇哪種方式取決於多種因素,包括索引有多窄,有多少行與謂詞匹配等。您可以使用
FORCESEEK
提示強制搜尋,但我懷疑它最終會執行相同或更差SQL Server 在您的情況下選擇的掃描。一些選項:
- 更改應用程序以執行正確的查詢。我首先列出這個是有原因的。
- 創建一個僅選擇您需要的列的視圖:
CREATE VIEW dbo.myview WITH SCHEMABINDING AS SELECT col1, col2, col3 FROM dbo.tablename;
然後,您可以
SELECT *
從此視圖更改應用程序。或者您可以更有創意並重命名原始表格,並將此視圖的名稱更改為表格的名稱。明顯的改變;謹慎行事。 3. 將所有其他列添加到索引的鍵或INCLUDE
列表中。如果這些是硬編碼值並且總是使用的值,您可以考慮使用過濾索引。