我正在尝试提高运行速度非常慢的查询的性能。完成实际执行计划之后;我发现 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]
答案 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)
重建索引,并计算统计数据?
我能想到加速它的另一种方法是对表格进行分区,这可能是也可能是不可能的。