2012-06-28 114 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

相关问题