0

我对 SQLServer 相当陌生,有一件事让我很困扰。希望你们中的一个可以向我解释发生了什么。

当我在索引过程中运行活动监视器时,我意识到包括弱实体在内的一些查询花费的时间比预期的要长,而且 - 甚至更奇怪 - SQLServer 建议在表单的弱实体上创建索引

CREATE NONCLUSTERED INDEX [<INDEXNAME>]
ON [dbo].[<TABLE>] ([<ID1>])
INCLUDE ([<ID2>])
GO

这样做(实际上我索引了两列,但我认为结果几乎相同)确实提高了查询速度(至少从我在活动监视器中看到的)。

CREATE UNIQUE NONCLUSTERED INDEX [<INDEXNAME>] ON [dbo].[<TABLE>] 
(
    [<ID1>] ASC,
    [<ID2>] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

我现在的问题是:SQLServer 是否忽略聚集索引?如果是,为什么?我能以某种方式解决这个问题吗?添加另一个实际上应该与主键索引具有完全相同内容的索引对我来说似乎很奇怪。

4

1 回答 1

2

可能有多种原因 - 向我们展示您的聚集索引的定义以澄清。

如果您的聚集索引在 ID2、ID1 上,并且您在查询中选择了两列,但在 where 子句中使用了 ID1,那么这个新的非聚集索引会运行得更快是有道理的。

如果您只有 1 列上的非聚集索引但要选择两列,那么它必须转到聚集索引来查找数据,因此在这种情况下,将第二列添加为 INCLUDEd 列甚至是第二个索引列可以避免SQL 服务器必须接触数据页。

另一方面,如果您的聚集索引的顺序相同,则它可以是以下任何一种:

  1. 聚集索引的填充因子 - 如果填充因子较低,则数据分布在比需要更多的数据页上,并且可能比从更密集的非聚集索引中读取数据要慢
  2. 聚集索引所在的文件组(最终是磁盘) - 如果不同,查询优化器可能会识别聚集索引磁盘上的高争用或慢速寻道速度
  3. 您一直在将顺序数据插入到聚集索引中,并且聚集索引 b-tree 现在是不平衡的
  4. 表中发生了许多插入,导致许多页面拆分,导致数据在聚集索引上没有物理顺序
  5. 您的聚集索引不是唯一的 - 在这种情况下,SQL 服务器将向您的聚集索引添加一个唯一标识符,使其比等效的非聚集索引更大,因此要读取的数据更多,因此速度更慢
  6. 您的聚集索引仅在 1 列上(见下文)

如果您在 1 列(例如 ID1)上有聚集索引,则索引数据是对索引的 2 次逻辑读取,但 ID2 列数据位于索引的叶子上,即 3 次读取深度。

对于等效的非聚集索引,它只需要 2 次逻辑读取,因为它不必访问数据页,这意味着非聚集索引将快 1/3。

查看聚集索引和非聚集索引是如何存储的:

聚集索引结构

非聚集索引结构

让我知道是哪一个!

于 2012-11-22T00:17:03.157 回答