为什么SQL Server 2005会更有效地执行表扫描而不是使用主键上的可用聚簇索引(并且只使用主键)?
声明: 还主键上的非群集,非唯一索引,没有包含列。这让我感到困惑,我们已经有一个好办公室笑了。如果这个指数最终成为问题,那么我们就知道该拍哪个。不幸的是,它是一个生产网站,我不能把它撕掉,但如果有必要的话会制定计划。
可能问题不是精神缺陷的相反指数,但是......
根据FogLight PASS,当我们通过主键删除一行时,以下语句已导致在一个表上扫描约1000万行,每小时约600次:
DELETE FROM SomeBigTable WHERE ID = @ID
表DDL:
CREATE TABLE [SomeBigTable]
(
[ID] [int] NOT NULL,
[FullTextIndexTime] [timestamp] NOT NULL,
[FullTextSearchText] [varchar] (max) NOT NULL,
CONSTRAINT [PK_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
) -- ...
ON PRIMARY
聚集索引约束详细信息:
ADD CONSTRAINT [PK_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
) WITH PAD_INDEX = OFF
,STATISTICS_NORECOMPUTE = OFF
,SORT_IN_TEMPDB = OFF
,IGNORE_DUP_KEY = OFF
,ONLINE = OFF
,ALLOW_ROW_LOCKS = ON
,ALLOW_PAGE_LOCKS = ON
,FILLFACTOR = 75
ON PRIMARY
同一个表上的非唯一非聚集索引:
CREATE NONCLUSTERED INDEX [IX_SomeBigTable_ID] ON [SomeBigTable]
(
[ID] ASC
) WITH PAD_INDEX = OFF
,STATISTICS_NORECOMPUTE = OFF
,SORT_IN_TEMPDB = OFF
,IGNORE_DUP_KEY = OFF
,ONLINE = OFF
,ALLOW_ROW_LOCKS = ON
,ALLOW_PAGE_LOCKS = ON
,FILLFACTOR = 98
ON PRIMARY
还 [ID]列上的外键约束指向同样大的表。
使用相同的语句,600个表扫描大约是该表每小时总删除操作的约4%。因此,并非所有此语句的执行都会导致表扫描。
毋庸置疑,但无论如何都要这样说......这是我要发送包装的很多令人讨厌的I / O.
答案 0 :(得分:1)
您是否尝试在桌面上重新计算statistics并清除proc cache? 例如像这样的东西:
USE myDatabase;
GO
UPDATE STATISTICS SomeBigTable;
GO
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
可能是sql server只是使用了错误的索引,因为当表中有不同的数据时,缓存的计划很糟糕。
答案 1 :(得分:1)
有些事要尝试,有些事要检查:
您是否正在运行DELETE SomBigTable where ID = @Parameter
声明?如果是这样,是类型为int的@Parameter,还是与被删除的列不同的数据类型? (可能不是这样,但是我遇到了一个字符串被转换为unicode的情况,这导致了一个索引被忽略。)
制作数据库的副本并乱用它:
可能不是这些,但是在弄乱它们时你可能会遇到真正的问题。