繁体   English   中英

SQL Server - 查询执行索引扫描而不是搜索

[英]SQL Server - Query performs Index Scan instead of Seek

我正在使用Lucene索引CMS的内容,因此我扩展了SQL Server数据库模式以添加“IsIndexed”位列,因此Lucene索引器可以找到一段尚未存在的内容索引。

我在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的聚簇索引搜索。 查询大约需要300毫秒才能执行。

当我修改查询以删除Users.UserName字段和用户内部联接时,查询运行大约需要60ms,并且没有针对PK_Content的聚簇索引扫描,只有聚集索引搜索PK_Content。

我在为Content.IsIndexed列添加降序索引之前和之后尝试了这个,我还将Content.DocumentId添加到了IX_Indexed索引,但它没有任何区别。

我究竟做错了什么? 我已经制作了所有必要的索引(然后是一些)。 Content表有数十万行,类似于Users表,所以我看不出优化器选择扫描的原因。

使用IsIndexed字段和AuthorUserId字段向Content添加索引,然后应该执行搜索。 根据您的SQL Server版本,您可以添加INCLUDE语句,其中包含您在select中使用的字段,以获得更快的速度。

IX_Indexed_AuthorUserId(非唯一,非群集):IsIndexed,AuthorUserId

这种低选择性列的索引(只有两个值0和1)总是会被忽略,参见引爆点 一种选择是将其作为聚集索引中最左侧的键移动,并使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;

第二种选择可能会复制很多内容。 就个人而言,我会选择第一个选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM