SQL Server上的SQL Server查询执行与Management Studio有何不同?

时间:2015-08-06 12:04:53

标签: sql .net sql-server full-text-search

我在针对SQL Server 2008 R2上的全文搜索数据库运行某组搜索(来自.NET 3.5应用程序)时调查了一个问题。使用分析器我解析了长时间运行的查询(120秒,直到达到命令超时)并在我的SQL Server Management Studio中运行它。持续时间为“0秒”,取决于我尝试了哪一个,返回了0到6行。

查询如下所示:

SqlConnection conn = new SqlConnection("EXACTSAMECONNECTIONSTRING_USING_SAME_USER_ETC")
conn.Open();
SqlCommand command = conn.CreateCommand()
command.CommandText = "EXACTLY SAME STRING, LITERALLY, AS ABOVE IN SSMS- exec sp_executessql.....";
command.CommandTimeout = 120;
var reader = command.ExecuteReader();
while(reader.NextResult())
{
    Console.WriteLine(reader[0]);
}

查询看起来有点奇怪,因为它是从OR Mapper生成的,但是现在我不想优化查询,就像SSMS在不到一秒的时间内运行一样,这表明它不是真正的查询制造麻烦。

我写了一个小的测试程序:

(button A, button B, button C)

当我执行命令超时120秒后,我从本地PC获得了一个SQLException。

SQL Server的负载不会超过几个百分点。在我的测试期间,该表上没有任何区块。

我在一段时间后解决了这个问题:我将TOP 1000减少到TOP 200,突然间,.NET代码的查询也在不到一秒的时间内完成。

我的问题:

  1. 为什么SSMS和最简单的SQLCommand .NET代码之间存在如此巨大的差异?
  2. 为什么减少到TOP 200有任何影响,特别是考虑到结果中最多有6行。

2 个答案:

答案 0 :(得分:2)

这与查询计划的构建方式有关。当您在SSMS中运行它时,您可能手动替换变量,因此它们不一样。

您可以在此处阅读完整说明:http://www.sommarskog.se/query-plan-mysteries.html

编辑:可能从段落开始#34;默认设置"并通过手动启用或禁用ARITHABORT查看结果。这是最常见的原因。

答案 1 :(得分:2)

因此,初步答案(由于其复杂性尚未完全验证)可以从Keorl的答案中得出,或者主要来自其中提供的链接。

为了描述不同的症状,我将解释会发生什么:

SQL Server根据全文索引表缓存查询,该表包含查询的执行计划。这意味着,如果要运行的第一个查询(将计划放入缓存)是一个非常罕见的查询,并且执行计划很荒谬,则此计划将被缓存并用于所有后续查询,从而破坏大多数运行的性能。

我最终可以重现一件事:重新运行FT索引器/收集器解决了问题(这一次)。此处的解释也很简单:索引更新会抛弃预编译/缓存的查询。因此,比以前缓存的查询更好的查询可以作为第一个运行,并在缓存中存储更好的整体计划。

回答Q1:为什么SSMS和最简单的SQLCommand .NET代码之间存在如此巨大的差异?

那为什么SSMS不会发生这种情况呢?这也可以从Keorl的答案中提取出来:SSMS在设置ARITHABORT选项时绕过了这个,导致它自己新编译的查询然后被缓存。因此,仅使用SSMS和Code对同一查询的不同观察结果。

回答Q2:为什么减少到TOP 200有任何影响,特别是考虑到结果中最多有6行?

对于上面示例中使用的动态SQL,根据完整查询的哈希值存储缓存。由于TOP 200和TOP 1000的查询不同,因此会缓存两个不同的编译。参数不是散列的一部分,因此只更改参数的查询仍然会导致使用相同的缓存条目。

结论:感谢Keorl提供找到答案的方法。