选择前10名...并选择前30名遵循不同的执行计划

时间:2011-11-17 16:14:55

标签: sql-server query-optimization sql-server-2008-r2

在查询优化期间,我编写了一个奇怪的sql server行为(Sql Server 2008 R2 Enterprise)。我在表上创建了几个索引,以及一些索引视图。我有两个问题,例如:

select top 10 N0."Oid",N1."ObjectType",N1."OptimisticLockField" from ((("dbo"."Issue" N0
 inner join "dbo"."Article" N1 on (N0."Oid" = N1."Oid"))
 inner join "dbo"."ProductLink" N2 on (N1."ProductLink" = N2."Oid"))
 inner join "dbo"."Technology" N3 on (N2."Technology" = N3."Oid"))
where (N1."GCRecord" is null and (N0."IsPrivate" = 0) and ((N0."HasMarkedAnswers" = 0) or N0."HasMarkedAnswers" is null) and (N3."Name" = N'Discussions'))
order by N1."ModifiedOn" desc

select top 30 N0."Oid",N1."ObjectType",N1."OptimisticLockField" from ((("dbo"."Issue" N0
 inner join "dbo"."Article" N1 on (N0."Oid" = N1."Oid"))
 inner join "dbo"."ProductLink" N2 on (N1."ProductLink" = N2."Oid"))
 inner join "dbo"."Technology" N3 on (N2."Technology" = N3."Oid"))
where (N1."GCRecord" is null and (N0."IsPrivate" = 0) and ((N0."HasMarkedAnswers" = 0) or N0."HasMarkedAnswers" is null) and (N3."Name" = N'Discussions'))
order by N1."ModifiedOn" desc

两个查询都是相同的,但首先以选择前10名开始,第二次使用选择前30名。两个查询都返回相同的结果集 - 6行。但第二个查询比第一个快5倍!我查看了两个查询的实际执行计划,当然,它们有所不同。第二个查询使用索引视图,执行得很好,第一个查询拒绝使用它,而是使用表上的索引。我重复一遍 - 两个查询都是相同的,在同一个表中,在同一个服务器上,它们仅在“顶部”部分中的数字不同。 我试图通过更新统计信息,销毁它使用的索引等强制优化器在第一个查询中使用索引视图。无论我如何尝试实际执行,都不要对第一个查询使用索引视图,并始终将其用于第二个查询。

我对引起这种行为的原因感到非常兴奋。有什么建议吗?

更新我不确定它可以帮助而不需要描述相应的索引和视图,但这是实际的执行计划图: 选择前19名: for select top 19:

选择前18名: for select top 18:

另一个令人困惑的事实是,对于select top 19查询,有时使用索引视图,有时不使用

1 个答案:

答案 0 :(得分:1)

我唯一能想到的可能是第一个查询中的优化器得出结论,指定标准对于“更好”的执行计划的选择性不够。

如果你还在调查这个,看看TOP 60,90,100,......是否产生了第二个执行计划并且表现良好。您还可以修改它以查看优化器在这种情况下选择第二个计划的阈值。

同时尝试不带order by语句的查询,看看是否影响了查询计划的选择(检查该字段的索引等)

除此之外,你说你不能使用索引提示,所以也许重写一下你从Article表(N1)中选择top X并在where子句中使用一堆exists语句为你提供更好的性能。