Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
需要有关SQL Server 2005上SQL查询的帮助吗_Sql_Sql Server 2005_Nhibernate - Fatal编程技术网

需要有关SQL Server 2005上SQL查询的帮助吗

需要有关SQL Server 2005上SQL查询的帮助吗,sql,sql-server-2005,nhibernate,Sql,Sql Server 2005,Nhibernate,在SQL Server 2005上运行两个版本的查询时,我们会看到奇怪的行为: A版: 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 = 12

在SQL Server 2005上运行两个版本的查询时,我们会看到奇怪的行为:

A版:

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版平均需要4秒。 有人能帮助我们理解这两个版本的SQL在执行时间上的差异吗

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

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一样糟糕。

请查看查询的执行计划。这将为您提供有关如何执行查询的更多解释。

请尝试查看查询的执行计划。这将为您提供有关如何执行查询的更多解释。

可能不是将1234强制转换为与listcontacts.listid相同的类型,然后对每一行进行比较,而是将每一行中的值强制转换为与1234相同的值。第一个只需要一次强制转换,第二个需要每行强制转换一次(可能远远超过1000行,可能是表中的每一行)。我不确定该常量将被解释为什么类型,但它可能是“数值”而不是“int”

如果这是原因,那么第二个版本会更快,因为它强制将1234解释为int,从而消除了在每一行中强制转换值的需要


但是,如前一张海报所示,SQL Server Management Studio中显示的查询计划可能表明另一种解释。

可能不是将1234转换为与listcontacts.listid相同的类型,然后对每行进行比较,而是将每行中的值转换为与1234相同的值。第一个只需要一次强制转换,第二个需要每行强制转换一次(可能远远超过1000行,可能是表中的每一行)。我不确定该常量将被解释为什么类型,但它可能是“数值”而不是“int”

如果这是原因,那么第二个版本会更快,因为它强制将1234解释为int,从而消除了在每一行中强制转换值的需要


但是,正如前一张海报所示,SQL Server Management Studio中显示的查询计划可能表明了另一种解释。

查看正在发生的情况的最佳方法是比较执行计划,其他一切都是基于问题中提供的有限细节的推测


要查看执行计划,请进入SQL Server Management Studio并运行
SET SHOWPLAN_XML ON
,然后运行查询版本A,查询将不会运行,但执行计划将以XML显示。然后运行查询版本B并查看其执行计划。如果您仍然无法分辨差异或解决问题,请发布两个执行计划,这里会有人对此进行解释。

了解情况的最佳方法是比较执行计划,其他一切都是基于问题中有限细节的推测


要查看执行计划,请进入SQL Server Management Studio并运行
SET SHOWPLAN_XML ON
,然后运行查询版本A,查询将不会运行,但执行计划将以XML显示。然后运行查询版本B并查看其执行计划。如果您仍然无法分辨差异或解决问题,请发布这两个执行计划,这里会有人解释。

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

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

那么,您可以做些什么来改进场景呢?这里有两种选择:

1) 创建存储过程以执行以下查询:

创建程序Foo @Id INT 像 选择otherattributes.*从列表联系人加入otherattributes 在listcontacts.contactId=otherattributes.contactId上,其中listcontacts.listid=@Id 按名称订购ASC

这将允许优化人员在传入时嗅探输入参数的值,并为第一次执行生成适当的执行计划。不幸的是,它将缓存该计划以供以后重用,因此除非您通常使用类似的选择性值调用存储过程,否则这可能不会对您有太大帮助

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

3) 将选项(重新编译)添加到SQL语句的末尾。强制重新编译此语句,并能够优化输入值


4) 在SQL语句的末尾添加选项(优化(@Id=1234))。这将导致缓存的计划为此特定输入值进行优化。如果这是一个非常常见的值,或者大多数常见的值具有类似的选择性,那就太好了,但是如果选择性分布更广泛,就不太好了。

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

在第二种情况下,优化者无法嗅探ID的值,因此生成的计划对于任何传入的列表ID都是可接受的。我说的可接受并不意味着最优。