2011-12-01 56 views
2

我在SQL Server中的表2008數據庫:SQL服務器,爲什麼不使用索引

CREATE TABLE [dbo].[Actions](
    [ActionId] [int] IDENTITY(1,1) NOT NULL,  
    [ActionTypeId] [int] NOT NULL, 
    [Name] [nvarchar](50) NOT NULL, 
    [Description] [nvarchar](1000) NOT NULL, 
    [Comment] [nvarchar](500) NOT NULL, 
    [Created] [datetime] NOT NULL, 
    [Executed] [datetime] NULL, 
    [DisplayText] [nvarchar](1000) NULL,  
    [ExecutedBy] [int] NULL, 
    [Result] [int] NULL 
) 
CONSTRAINT [PK_Actions] PRIMARY KEY CLUSTERED 
(
    [CaseActionId] ASC 
) 
) ON [PRIMARY] 

GO 


CREATE NONCLUSTERED INDEX [IX_Actions_Executed] ON [dbo].[Actions] 
(
    [Executed] ASC, 
    [ExecutedBy] ASC 
) 

有已經執行日期等於「2500年1月1日」和420 000列20行000已執行日期<'2500-01-01'。

當我執行一個查詢

select CaseActionId, Executed, ExecutedBy, DisplayText from CaseActions 
where Executed='2500-01-01' 

查詢計劃表明,在PK_Actions聚集索引執行掃描和索引IX_Actions_Executed完全不使用。

我有什麼有趣的缺失索引提示它說

/* The Query Processor estimates that implementing the following index could improve the query cost by 99.9901%. 
*/ 

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] 
ON [dbo].[Actions] ([Executed]) 

不過該指標已經存在。

爲什麼索引不被使用,如果它會選擇5%的數據?

回答

3

最有可能的,查詢優化器只是看到您要選擇DisplayText以及 - 因此每個在NC指數發現20'000行的,就需要一個鍵查找到聚集索引獲取該數據 - 並且鍵查找昂貴的操作!因此,最終,立即掃描clustere索引可能會更容易,更高效。

我敢打賭,如果你在這裏運行此查詢:

select CaseActionId, Executed, ExecutedBy 
from CaseActions 
where Executed='2500-01-01' 

那麼NC指數將用於

如果你真的需要DisplayText,這就是你經常運行的查詢,也許你應該包括在索引列在葉級別一個額外的列:

DROP INDEX [IX_Actions_Executed] 

CREATE NONCLUSTERED INDEX [IX_Actions_Executed] 
ON [dbo].[Actions]([Executed] ASC, [ExecutedBy] ASC) 
INCLUDE([DisplayText]) 

這將使您的NC指數覆蓋指數,即它可以返回查詢所需的所有列。如果你再次使用這個覆蓋索引來運行你的原始查詢,我很肯定SQL Server的查詢優化器確實會使用它。如果NC指數是覆蓋指數,例如,將使用任何NC指數的概率爲,則顯着增加。有些查詢可以從NC索引中獲得他們所需的所有列,而無需查找關鍵字。

缺少的索引提示有時會有點誤導 - 還有一些已知的錯誤可導致SQL Server Mgmt Studio不斷推薦已經存在的索引.....不要將太多的錢投入到這些索引提示!

+0

是的,你是正確的顯示文本。你說20000鍵查找比整個聚簇索引的掃描要貴?好的,謝謝你的信息。 – WaldiMen

+0

@WaldiMen:測試它! :-)你可以強制SQL Server通過'WITH(INDEX(IX_Actions_Executed))'來使用索引 - 比較執行計劃,執行時間和I/O統計。另外:嘗試**覆蓋索引**的方法 - 我敢肯定,如果包含「DisplayText」列,它將被使用.... –