如何提高聚簇索引的性能

时间:2009-12-28 19:15:09

标签: sql sql-server query-performance sql-execution-plan

我正在尝试提高运行速度非常慢的查询的性能。完成实际执行计划之后;我发现 Clustered Index Seek 占82%。我有什么办法可以改善 Index Seek 的表现吗?下面是执行计划中 Index Seek 的问题图像以及它正在使用的索引和表。

alt text http://img340.imageshack.us/img340/1346/seek.png

指数:

/****** Object:  Index [IX_Stu]    Script Date: 12/28/2009 11:11:43 ******/
CREATE CLUSTERED INDEX [IX_Stu] ON [dbo].[stu] 
(
 [StuKey] ASC
)WITH (PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]

表格(为简洁起见省略了一些列):

CREATE TABLE [dbo].[stu](
 [StuCertKey] [int] IDENTITY(1,1) NOT NULL,
 [StuKey] [int] NULL
 CONSTRAINT [PK_Stu] PRIMARY KEY NONCLUSTERED 
(
 [StuCertKey] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]

9 个答案:

答案 0 :(得分:21)

我在这里概括,但是......

聚集索引查找在大多数情况下是最佳情况。我能想到提高绩效的唯一方法是:

  • 如果可能,更新查询以返回更少的行/列;
  • 对索引进行碎片整理或重建;
  • 跨多个磁盘/服务器对索引进行分区。

如果它只返回138行,那就慢......也许它被某些其他进程阻止了?您是单独测试这个,还是同时在线测试其他用户/进程?或者它甚至可能是硬件问题,例如磁盘故障。

答案 1 :(得分:12)

当使用非聚集索引并且不一定是坏的时,会发生聚簇索引。

考虑以下问题:

SELECT s.StuKey, s.Name, s.Address, s.City, s.State FROM stu s WHERE State='TX'

如果StuKey上只有聚簇索引,那么Sql Server只有1个选项,它必须扫描整个表,查找State =“TX”的行并返回这些行。

如果在State

上添加非聚集索引
CREATE INDEX IX_Stu_State on Stu (State)

现在Sql server有了一个新选项。它可以选择使用非聚集索引进行搜索,这将产生State ='TX'的行。但是,为了在SELECT中返回剩余的列,它必须通过对每一行执行聚簇索引查找来查找这些列。

如果你想减少聚集的索引搜索,那么你可以通过在其中包含额外的列来使你的索引“覆盖”。

 CREATE INDEX IX_Stu_State2 on Stu (State) INCLUDE (name, address, city )

此索引现在包含回答上述查询所需的所有列。查询将执行索引查找仅返回State ='TX'的行,并且可以从非聚集索引中提取其他列,因此聚集的索引搜索将消失。

答案 2 :(得分:7)

返回138行的聚簇索引范围搜索不是您的问题。

从技术上讲,您可以通过使聚簇索引更窄来提高搜索性能:

两者都可以对范围寻找时间产生相当大的影响,因为它们可以减少IO和物理读取的需要。当然,通常情况下,结果会因许多其他因素而异,例如您投影的列(将预计列驱逐到BLOB分配单元实际上可能会对某些查询产生负面影响)。作为旁注,通常碎片对这种短程扫描只会产生微不足道的影响。再次,这取决于。

但正如我所说,我非常怀疑这是你真正的问题。您只发布了计划的选定部分和您自己的分析结果。真正的根本原因可能完全在其他地方。

答案 3 :(得分:3)

...思想

  • 为什么IX_Stu会聚集?在内部,SQL Server向非唯一聚簇索引添加了一个4字节的“唯一符号”。理由是什么?这也会让你的PK气喘吁吁

  • 您正在运行的实际查询是什么?

  • 最后,为什么FILLFACTOR 80%?

编辑:

  • “普通”FILLFACTOR为90%,但这只是经验法则

  • 11个连接查询?这很可能是你的问题。你的JOIN,WHERE条款等是什么?什么是全文计划?

答案 4 :(得分:1)

您是否尝试过对此索引进行一些维护?碎片整理吗?看起来真的很奇怪它花了很多钱(120.381)。索引搜索是最快的索引操作,不应该花那么长时间。你可以发帖查询吗?

答案 5 :(得分:1)

如果您对 WHERE 条件进行硬编码会发生什么情况,例如:

SELECT StuCertKey, StuKey FROM stu 
WHERE stuKey in (/* list 50 values of StuKey here */)

如果它仍然很慢,你会遇到某种内部问题。如果它更快,那么索引不是你的瓶颈,你正在做的 JOINs 来创建 WHERE 过滤器。

请注意,如果有很多大列,SELECT *可能会非常慢,特别是如果有BLOB。

答案 6 :(得分:1)

一些一般建议:当我必须进行查询优化时,我首先要写出我认为执行计划应该是什么。

一旦我确定了我认为执行计划应该是什么,我会尝试使实际查询符合此计划。对于每个DBMS,执行此操作的技术是不同的,并且不一定在不同版本的DBMS之间,甚至有时在不同版本的DBMS之间传输。

要记住的是DBMS一次只能执行一个连接:它从两个初始表开始,加入这些连接,然后获取该操作的结果并将其连接到下一个表。每个步骤的目标是最小化中间结果集中的行数(更准确地说,最小化必须读取以产生中间结果的块数,但这通常意味着最少的行)。

答案 7 :(得分:1)

检查指数统计数据。

重新计算聚簇索引统计信息将解决问题。

在我的情况下,我正在寻找40M记录的30条记录。 执行计划说它正在通过聚集索引,但它花了大约200ms。并且索引未进行碎片整理。重新计算它的统计数据后,它将在10毫秒内完成!

答案 8 :(得分:0)

重建索引,并计算统计数据?

我能想到加速它的另一种方法是对表格进行分区,这可能是也可能是不可能的。