2012-06-28 111 views
1

我正在使用Lucene索引CMS的內容,所以我擴展了SQL Server數據庫模式以添加一個「IsIndexed」位列,所以Lucene索引器可以找到尚未編入索引的內容。SQL Server - 查詢執行索引掃描而不是查詢

我在Content表中添加了一個索引,因此IsIndexed列的查找速度應該更快。這是數據庫的樣子:

CREATE TABLE Content (
    DocumentId bigint, 
    CategoryId bigint, 
    Title nvarchar(255), 
    AuthorUserId bigint, 
    Body nvarchar(MAX), 
    IsIndexed bit 
) 
CREATE TABLE Users (
    UserId bigint, 
    UserName nvarchar(20) 
) 

以下指標存在:

Content (
    PK_Content (Clustered) : DocumentId ASC 
    IX_CategoryId (Non-Unique, Non-Clustered) : CategoryId ASC 
    IX_AuthorUserId (Non-Unique, Non-Clustered) : AuthorUserId ASC 
    IX_Indexed_ASC (Non-Unique, Non-Clustered) : IsIndexed ASC, DocumentId ASC 
    IX_Indexed_DESC (Non-Unique, Non-Clustered) : IsIndexed DESC, DocumentId ASC 
) 

Users (
    PK_Users (Clustered) : UserId 
) 

這是用來查找非索引內容查詢:當我運行它的

SELECT 
    TOP 1 
    Content.DocumentId, 
    Content.CategoryId, 
    Content.Title, 
    Content.AuthorUserId, 
    Content.Body 
    Users.UserName 
FROM 
    Content 
    INNER JOIN Users ON Content.AuthorUserId = Users.UserId 
WHERE 
    IsIndexed = 0 

然而實際執行計劃報告PK_Content的聚集索引掃描與PK_Users的聚集索引搜索相結合。查詢需要大約300ms才能執行。

當我修改查詢以刪除Users.UserName字段和Users內部連接時,查詢大約需要60ms才能運行,並且沒有用於PK_Content的集羣索引掃描,只有集羣索引尋找PK_Content。

我在爲Content.IsIndexed列添加降序索引之前和之後嘗試過,我還將Content.DocumentId添加到IX_Indexed索引,但它沒有區別。

我在做什麼錯?我做了所有必要的索引(然後是一些)。內容表有成千上萬的行,類似於Users表,所以我不明白爲什麼優化器會選擇掃描。

+0

是否有任何索引?如果所有行(或大多數行)的IsIndexed等於0,則索引不太可能被使用 –

+0

大約30%的所有內容行都有IsIndexed = 1 – Dai

回答

1

在這樣一個低選擇性柱(只有兩個值0和1)總是將被忽略的索引,見the tipping point。一種選擇是將其移動作爲聚集索引最左邊的鍵,使主鍵約束上DocumentId一個非聚集索引:

CREATE TABLE Content (
    DocumentId bigint, 
    CategoryId bigint, 
    Title nvarchar(255), 
    AuthorUserId bigint, 
    Body nvarchar(MAX), 
    IsIndexed bit, 
    constraint pk_DocumentId primary key nonclustered (DocumentId) 
) 

create unique clustered index cdxContent on Content (IsIndexed, DocumentId); 

另一種選擇是創建一個過濾覆蓋指數:

create unique index nonIndexedContent on Content (DocumentId) 
    include (CategoryId, Title, AuthorUserId, Body) 
    where IsIndexed = 0; 

這第二個選項可能會重複很多內容。就我個人而言,我會選擇第一個選項。

2

使用IsIndexed字段和AuthorUserId字段向內容添加索引,則應該執行搜索操作。根據您的SQL服務器版本,您可以添加一個INCLUDE語句和您在select中使用的字段,以獲得更高的速度。

IX_Indexed_AuthorUserId(非唯一的,非羣集):IsIndexed, AuthorUserId

+0

謝謝。在添加該索引之後,實際查詢執行計劃報告它執行了兩個索引查找並且沒有索引掃描,但查詢仍然需要大約300ms才能運行。 – Dai

相關問題