SQL Server - 索引搜索预期的索引扫描

时间:2014-10-07 00:21:14

标签: sql sql-server indexing

我正在尝试删除索引扫描,但我似乎无法弄清楚如何使用我目前的理解来进行搜索。我看过整个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有条件地链接它们。动作。

目前的PK /指数:

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

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

DocumentTypeId是int not null。

查询计划最终产生:

  • 哈希匹配(聚合)12%< =
  • 哈希匹配(内部联接)57%< =
  • 索引扫描(NonClustered)[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]
)

1 个答案:

答案 0 :(得分:0)

我宁愿从dbo.Activity表上的索引开始。现有的那些都不适合这个查询,但其中一个应该是诀窍:

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

dbo.UserDocument表上的索引就好了。

哦,是的,在排序时将datetime列投射到date是没有意义的。它不会给你任何有用的东西,但肯定会毁掉你可能拥有的索引的任何好处。