2010-05-27 85 views
3

我有以下查询:简单查询帮助 - 为什么不是索引被使用?

SELECT MAX([LastModifiedTime]) FROM Workflow 

有大约在工作流程表400M行。 LastModifiedTime列上的索引如下:

CREATE NONCLUSTERED INDEX [IX_Workflow_LastModifiedTime] ON [dbo].[Workflow] 
(
[LastModifiedTime] 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, FILLFACTOR = 100) 

上述查询需要1.5分钟执行。为什么SQL Server不使用上述索引并简单地检索索引中的最后一行以获取最大值?

顺便说一下,该查询的查询计划显示index scan正在完成上述索引。

谢谢。

+0

你可以尝试做一个'UPDATE STATISTICS dbo.Workflow'或'UPDATE STATISTICS dbo.Workflow IX_Workflow_LastModifiedTime',看看是否有什么差别? – 2010-05-27 18:59:54

+0

@marc_s - 它使用索引,但它正在扫描它。为什么它不会落到最后一行呢?这将是最大的价值。除非需要1:30才能在索引中有400M行时下降到最后一行? – 2010-05-27 19:07:04

+0

是的,也许如果你更新的统计数据,查询优化器会发现有太多的行只是扫描 - 并找到一些其他的策略来得到所需的结果.... – 2010-05-27 20:26:06

回答

3

神秘的查询优化的方式...

如果有可能,我建议你改变这样的查询:

SELECT TOP (1) [LastModifiedTime] 
FROM Workflow 
ORDER BY [LastModifiedTime] DESC; 

这是语义相同和优化器将不再考虑使用MAX聚合和扫描(显然它现在正确)。它可能会考虑在工作台上做一个SORT,但希望这样一个计划的估计成本将远大于逆向寻求的成本。

至于为什么优化器选择显然是一个明显不好的计划,通常涉及很多因素,很难从SO帖子诊断。一般来说,拥有ASC索引并不总是替代缺少DESC索引,而且您的特定列统计信息(分发信息)可能已经在查询优化程序内达到了某个临界点,因此它决定选择scan + aggregate而不是反向扫描+顶部。

0

你可以从执行计划中知道它是否使用索引?如果不是,最后一次分析表/索引的时间是?如果它从来没有被分析过,也许SQL服务器仍然认为它只有100行,并且执行表扫描会更快。

+0

本专栏的索引仅在两小时前添加。他们的查询计划显示索引扫描正在索引上完成。 – 2010-05-27 18:54:08

+3

@Randy Jut出于好奇,这个查询需要多长时间:'SELECT TOP 1 LastModifiedTime FROM WorkFlow ORDER BY LastModifiedTime DESC' – 2010-05-27 19:06:53

+0

没有真正的区别。索引扫描仍在进行中。 – 2010-05-27 19:25:55

1

我有一个类似日期时间字段(假设是你的数据类型)和4M行的表 - 你的1%,但同样的查询几乎只要我点击'执行'就回来了。我的指数几乎和你的一样:

CREATE NONCLUSTERED INDEX [IX_PartViewTrack_SearchDate] ON [dbo].[PartViewTrack] 

(
[SearchDate] 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] 

的执行计划显示索引扫描。

只是咧嘴笑 - 下降的指数,看看需要多长时间?

0
SELECT MAX([LastModifiedTime]) FROM Workflow with(nolock) 

这是否更快?

+0

它可能稍微快一些,但真正的问题是它正在执行索引扫描而不是查找。添加(nolock)不会改变这一点。 – 2010-05-27 19:24:40

0

一个黑白问题,没有(对我)一个明显的答案。这里有一些非常愚蠢的想法,只是为了清除空气。

  • 这是表吗?如果一个视图,底层 结构可能会阻碍。 (I 忘记了,您可以在物化视图上创建非集群 索引吗?)

  • 是否存在争用?如果其他用户 在 表上有长期锁定,则可能会降低它的速度。 此外,极其频繁的更新 可能会抛出。

  • 查询计划显示索引扫描 正在运行。索引是否参考 这个索引? (还有其他的指标?一个聚集索引? 可能不是一个问题,而是观念摸索 这里。)

  • 你使用模式?索引是 dbo.Workflow,但查询不包含 指定“dbo”。 (就像我说的, 摸索的想法在这里。)

所有这些听起来很蹩脚的,但没有动手访问这些类型的问题可能是非常艰难弄清楚。

0

这是一个很长的画面:我发现Oracle有时需要一个字段在它将使用索引之前不允许空值。 SQL Server中是否有类似的限制?

0

分析索引首先使用命令

DBCC SHOW_STATISTICS (table_name, index_name) 

检查,如果你的指数是覆盖整个表。如果没有,请尝试更新的统计数据使用

UPDATE STATISTICS table_name