2010-04-27 80 views
1

运行SQL Server 2005上查询的两个版本时,我们看到了奇怪的现象:需要与SQL Server上的SQL查询帮助2005

版本答:

SELECT otherattributes.* FROM listcontacts JOIN otherattributes 
ON listcontacts.contactId = otherattributes.contactId WHERE listcontacts.listid = 1234 
ORDER BY name ASC 

版本B:

DECLARE @Id AS INT; 
SET @Id = 1234; 
SELECT otherattributes.* FROM listcontacts JOIN otherattributes 
ON listcontacts.contactId = otherattributes.contactId 
WHERE listcontacts.listid = @Id 
ORDER BY name ASC 

这两个查询都返回1000行;版本A平均需要15秒;版本B平均需要4s。 任何人都可以帮助我们理解这两个SQL版本的执行时间差异吗?

如果我们调用使用NHibernate通过命名参数此查询,我们看到通过SQL Server事件探查以下查询:

EXEC sp_executesql N'SELECT otherattributes.* FROM listcontacts JOIN otherattributes ON listcontacts.contactId = otherattributes.contactId WHERE listcontacts.listid = @id ORDER BY name ASC', 
    N'@id INT', 
    @id=1234; 

...这往往是表现不佳的版本A.

回答

2

试着看看你的查询的执行计划。这应该给你更多的解释你的查询是如何执行的。

0

可能不是将1234转换为与listcontacts.listid相同的类型,然后与每行进行比较,可能是将每行中的值转换为与1234相同的值。第一个参数只需要一个第二个需要每行进行一次强制转换(可能在1000行以上,可能是表中的每一行)。我不确定那个常量会被解释为什么类型,但它可能是'数字'而不是'int'。

如果这是原因,第二个版本更快,因为它强制1234被解释为一个int,因此不需要在每一行中投入值。

但是,正如前面的海报所示,SQL Server Management Studio中显示的查询计划可能会指出一个替代解释。

0

看到发生了什么的最好方法是比较执行计划,其他的一切都是根据问题中提出的有限细节进行推测。

要查看执行计划,进入SQL Server Management Studio并运行SET SHOWPLAN_XML ON,然后运行查询版本A,查询将不会运行,但执行计划将以XML显示。然后运行查询版本B并查看其执行计划。如果你仍然不能分辨或解决问题,那么发布两个执行计划,这里的某个人会解释它。

2

我还没有看到执行计划,但我强烈怀疑他们在这两种情况下是不同的。您遇到的问题是,如果A(更快的查询)优化程序知道您用于列表ID(1234)的值,并使用分布统计信息和索引组合选择最佳计划。

在第二种情况下,优化程序无法嗅探该ID的值,因此会生成一个计划,该计划对于任何传入的列表ID都是可接受的。而我所说的可接受的地方并不意味着最佳。

那么你可以做些什么来改善这种情况?有几个选择这里:

1)创建一个存储过程执行如下查询:

CREATE PROCEDURE富 @Id INT AS SELECT otherattributes * FROM listcontacts JOIN otherattributes ON listcontacts .contactId = otherattributes.contactId WHERE listcontacts.listid = @Id ORDER BY名ASC

GO

这将使优化器嗅探VALU当输入参数传入并为第一次执行产生适当的执行计划时。不幸的是,它会缓存该计划,以便稍后再次使用,除非您通常使用类似的选择性值调用存储过程,这可能无助于您太多

2)创建一个如上的存储过程,但将其指定为WITH RECOMPILE。这将确保存储过程每次执行时都会重新编译,从而生成针对此输入值优化的新计划。

3)将OPTION(RECOMPILE)添加到SQL语句的末尾。强制重新编译此语句,并且能够针对输入值进行优化

4)将OPTION(OPTIMIZE FOR(@Id = 1234))添加到SQL语句的末尾。这将导致缓存的计划针对此特定输入值进行优化。如果这是一个非常普遍的价值,或者最常见的价值观具有相似的选择性,但是如果选择性的分布更广泛地传播,那么它就不是那么好。