【发布时间】:2014-10-07 00:21:14
【问题描述】:
我正在尝试删除索引扫描,但以我目前的理解,我似乎无法弄清楚如何使其成为搜索。我查看了整个 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 不是对 UserDocument.UserDocumentId 的外键引用——它是一个松散的列,我们用来存储其他主键值,然后我们根据 Activity 有条件地链接到这些值。行动。
当前 PK/指数:
CONSTRAINT [pk_UserDocuments] PRIMARY KEY CLUSTERED
(
[UserDocumentId] ASC
)
CREATE NONCLUSTERED INDEX [ix_ud_dtid] ON [dbo].[UserDocument]
(
[DocumentTypeId] ASC
)
DocumentTypeId 是 int 不为空。
查询计划最终产生:
- 哈希匹配(聚合)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]
)
【问题讨论】:
-
很难说没有表结构和计划的更多细节。一个猜测是,在 ix_ud_dtid 索引中找到行后的 pk 查找成本被认为高于索引扫描。话虽如此,这个问题可能会在 dba.stackexchange 上找到更好的受众。
-
Activity 表上有索引吗?它们同样重要。
-
@TheVedge - 我添加了表格结构,看看它是否有助于绘制更清晰的画面。我在 SO 上看到了一些非常好的答案,但如果我在这里没有任何运气,我也会去 DBA。
-
@RogerF.Wolf - 我已经编辑了帖子以包含活动表中的索引。
-
@Mark 看看这个,它可能是多种因素的组合。我会说 ix_ud_dtid 用于在分组上节省一些周期。就行数而言,Activity 表是否比 UserDocument 大得多?此外,从它的外观上看,索引 Activity.ActivityObjectId 会给您带来更大的收益
标签: sql sql-server indexing