繁体   English   中英

SQL Server-在需要索引查找的位置进行索引扫描

[英]SQL Server - index scan where index seek expected

我正在尝试删除索引扫描,但是根据目前的理解,我似乎无法弄清楚如何进行索引扫描。 我看过整个SO的其他文章,这些文章表明索引中列的顺序需要正确,并且就我目前的理解而言,它们似乎是正确的,但我可能会完全不赞成。 也许订单根本不是答案。

这是查询:

DECLARE @ChartActions TABLE
(
    InValue INTEGER
);
INSERT INTO @ChartActions
VALUES
(73),
(74),
(75);

with cteGroupedChartActivity AS (
    SELECT MAX(ActivityId) as ActivityId
    FROM Activity
    JOIN UserDocument  ON Activity.ActionObjectId = UserDocument.UserDocumentId
    WHERE   Action IN (SELECT * FROM @ChartActions)
    GROUP BY UserDocument.DocumentTypeId,CAST(Activity.DateCreated AS DATE)
)
select * from cteGroupedChartActivity

我认为值得一提的是Activity.ActionObjectId不是对U​​serDocument.UserDocumentId的外键引用-它是一个散列,用于存储其他主键值,然后根据Activity.Action有条件地链接到该主键值。

当前的PK /指数:

CONSTRAINT [pk_UserDocuments] PRIMARY KEY CLUSTERED 
(
    [UserDocumentId] ASC
)

CREATE NONCLUSTERED INDEX [ix_ud_dtid] ON [dbo].[UserDocument]
(
    [DocumentTypeId] ASC
)

DocumentTypeId不为null。

查询计划最终产生:

  • 哈希匹配(总计)12% <=
  • 哈希匹配(内部联接)57% <=
  • 索引扫描(非聚集)[UserDocument]。[ix_ud_dtid] 28%

内部联接哈希匹配也溢出到tempdb中。 不知道这是否有用。

将鼠标悬停在索引扫描上时,实际记录数为468,392。

有什么想法吗? 我会显示图片,但没有代表。 我很乐意以任何方式提供所需的更多信息。

编辑1:

表结构如下:

CREATE TABLE [dbo].[Activity]
(
    [ActivityId] [int] IDENTITY(1,1) NOT NULL,
    [UID] [int] NULL,
    [Action] [int] NOT NULL,
    [ActionObjectId] [int] NOT NULL,
    [DateCreated] [datetime] NOT NULL,
    [PID] [int] NULL,
    [Data] [varchar](1024) NULL
)

CREATE TABLE [dbo].[UserDocument]
(
    [UserDocumentId] [int] IDENTITY(1,1) NOT NULL,
    [DocumentTypeId] [int] NOT NULL
)

dbo.Activity表上的索引:

CONSTRAINT [pk_Activity] PRIMARY KEY CLUSTERED 
(
    [ActivityId] ASC
)

CREATE NONCLUSTERED INDEX [ix_a_a__inc__aoid_dc_pid] ON [dbo].[Activity]
(
    [Action] ASC
)
INCLUDE
(
    [ActionObjectId],
    [DateCreated],
    [PID]
)

CREATE NONCLUSTERED INDEX [ix_a_pid_uid_a_aoid_dc_d] ON [dbo].[Activity]
(
    [PID] ASC
)
INCLUDE
(
    [UID],
    [Action],
    [ActionObjectId],
    [DateCreated],
    [Data]
)

我宁愿从dbo.Activity表上的索引开始。 现有的查询都不适合该查询,但是其中之一应该可以解决问题:

(Action, ActionObjectId)
(Action, ActionObjectId) include (DateCreated)
(Action, ActionObjectId, DateCreated)

您在dbo.UserDocument表上的索引就可以了。

哦,是的,在排序时将datetime列转换为date没有意义。 它不会给您任何有用的信息,但是肯定会破坏您可能拥有的索引的任何好处。

暂无
暂无

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

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