【发布时间】:2011-12-31 12:18:32
【问题描述】:
在查询优化期间,我遇到了 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
两个查询是相同的,除了第一个以 select top 10 开头,第二个以 select top 30 开头。两个查询都返回相同的结果集 - 6 行。但是第二个查询比第一个查询快 5 倍!我查看了这两个查询的实际执行计划,当然,它们是不同的。第二个查询使用索引视图,并且性能很好,而第一个查询拒绝使用它,而是使用表上的索引。我再说一遍 - 两个查询是相同的,对于同一个表,在同一个服务器上,它们仅在“顶部”部分中的数字不同。 我试图通过更新统计信息、销毁它使用的索引等来强制优化器在第一个查询中使用索引视图。无论我如何尝试实际执行,都不要将索引视图用于第一个查询,而始终将其用于第二个查询。
我对造成这种行为的原因非常感兴趣。有什么建议吗?
更新如果不描述相应的索引和视图,我不确定它是否有帮助,但这是实际的执行计划图: 选择前 19 名:
选择前 18 名:
另一个令人困惑的事实是,对于 select top 19 查询,有时使用索引视图,有时不使用
【问题讨论】:
-
索引视图是
FROM子句中提到的“表”之一吗?如果是这样,添加WITH (NOEXPAND)提示会改变什么吗? -
查询中不直接引用视图,只引用底层表。对于第二个查询,一切正常,但对第一个查询无效。事实上,我打开 SSMS 查询窗口,粘贴第二个查询 - 它使用索引视图,然后在查询和执行计划更改中将“前 30”替换为“前 10” - 根本不使用索引视图!
-
您是否在查询之间发出
DBCC FREEPROCCACHE; DBCC FREESYSTEMCACHE('ALL')以保证公平测试? -
只是一个左字段的想法,但您是否尝试过为 top (n) 语句使用变量?例如从...中选择顶部(@torows)
-
到@MicSim - 我试过 DBCC FREEPROCCACHE; DBCC FREESYSTEMCACHE('ALL') - 没有任何变化 - 两种情况的执行计划相同。
标签: sql-server query-optimization sql-server-2008-r2