【问题标题】:select top 10 ... and select top 30 follows different execution plan选择前 10 ... 并选择前 30 遵循不同的执行计划
【发布时间】: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


【解决方案1】:

我唯一能想到的可能是第一个查询中的优化器得出的结论是,指定条件的选择性不足以使用“更好”的执行计划。

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

还可以尝试不使用 order by 语句的查询,看看这是否会影响查询计划的选择(检查该字段上的索引等)

除此之外,您说您不能使用索引提示,因此也许重写您从文章表 (N1) 中选择 top X 并在 where 子句中使用一堆存在语句将为您提供更好的性能。

【讨论】:

  • 我无法修改查询。它由 ORM - Xpo 制作。我已经在“top”中尝试了不同的值——对于大于 25 的值,它总是选择索引视图并且执行计划很好。对于小于 17 的值,它始终不使用索引视图。感谢您的建议
  • 此外,查询性能不是一个大问题——还有很多其他方法可以解决这个问题。我对为什么回答这个问题更感兴趣?
猜你喜欢
  • 1970-01-01
  • 2014-02-10
  • 1970-01-01
  • 2015-11-13
  • 1970-01-01
  • 1970-01-01
  • 2015-07-06
  • 2023-02-21
  • 1970-01-01
相关资源
最近更新 更多