3

为什么 SQL Server 2005 会发现执行表扫描比使用主键(并且仅主键)上可用的聚集索引更有效?

免责声明:主键上还有一个非聚集、非唯一索引,没有包含列。这让我感到莫名其妙,我们已经在办公室笑得很好。如果这个指数最终成为问题,那么我们就知道该射击谁了。不幸的是,它是一个生产站点,我不能只是把它撕掉,但如有必要,我会制定计划。

也许问题不在于智力缺陷的相反指数,然而……

根据 FogLight PASS 的说法,当我们通过主键删除一行时,以下语句会导致每小时扫描约 600 次约 1000 万行的表:

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。

4

2 回答 2

1

您是否尝试过重新计算表上的统计信息并清除您的 proc缓存?例如这样的:

USE myDatabase;
GO

UPDATE STATISTICS SomeBigTable;
GO

DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS

可能是 sql server 只是使用了错误的索引,因为当表中有不同的数据时,它缓存了一个错误的计划。

于 2012-11-16T20:58:34.297 回答
1

有些事情要尝试,有些事情要检查:

你在DELETE SomBigTable where ID = @Parameter发表声明吗?如果是这样,@Parameter 是 int 类型,还是与被删除的列不同的数据类型?(可能不是,但我曾经遇到过一个字符串被转换为 unicode 的情况,这导致索引被忽略。)

制作数据库的副本并弄乱它:

  • 尝试确定哪些删除会导致扫描,哪些不会
  • 是否与FK相关表中数据的存在或不存在有关?
  • 外键是否可信(通过 sys.foriegn_keys 检查)
  • 放下 FK。它有什么改变吗?
  • 删除第二个索引。这有什么改变吗?

可能都不是这些,但是在与它们混在一起时,您可能会偶然发现真正的问题。

于 2012-11-16T21:09:49.313 回答