我为复杂视图创建了一个索引。在Sql Server管理工作室中运行以下查询需要0到几秒。查询计划显示99%的成本是在我为主要大表创建的索引的索引查找中。 (总子树成本为7.5)
select * from ComplexView where id = 10000 and theDate = '1/1/2018'
但是,以下查询
declare @id int = 10000, @theDate datetime = '1/1/2018'
select * from ComplexView where id = @id and theDate = @theDate
需要很长时间(3到10分钟),查询计划捕获显示57%的成本在主要大表上的表扫描上(加上10%过滤器和14%哈希匹配和17%排序,总子树成本为260)。
答案 0 :(得分:3)
第一个查询将根据文字10000
和'1/1/2018'
的值以及相关表格的直方图统计信息编制查询计划。
第二个基本上是"优化未知"因为在编译时认为参数的值是未知的。当您使用本地变量时,SQL Server无法再使用直方图。相反,它使用统计对象的密度向量信息。
这是已知的和预期的行为(尽管如果你不知道它可能会令人惊讶)。
您启用了显示两个查询的实际执行计划,发现他们有不同的计划。
如果您碰巧首先使用'典型的'值(基于所涉及的列的分布),您将获得适用于过滤器的大多数值的缓存计划。
假设您的统计信息是最新的,请尝试以下操作:
declare @id int = 10000, @theDate datetime = '1/1/2018'
select * from ComplexView
where id = @id and theDate = @theDate
option(recompile)
你有更合理的计划吗?
使用option(recompile)
是其中之一'它取决于'解答!如果查询是报告查询(我的意思是它运行时间相对较长且不经常运行),请考虑添加它。它告诉SQL Server不要缓存计划并在每次执行时重新编译新计划。它的缺点是您不会在缓存中看到该计划,并且在每次执行时支付计划编译的成本(与长时间运行的查询相比相对较小)。
如果它是关键报告查询,那么我会添加option(recompile)
以确保您永远不会得到不合适的查询计划。