为什么在打开SSMS的情况下会影响控制台应用程序?

5
我有一个控制台应用程序(C#),它连接到SQL数据库,执行存储过程,然后退出。 存储过程使用getdate和datediff来计时,并将计时结果返回给控制台应用程序。 存储过程始终报告执行时间约为100毫秒。
重复运行控制台应用程序会得到一组一致的计时结果 (包括ExecuteReader命令花费的300毫秒)。
然而我偶然发现并能够可靠地复现以下效果: 如果我打开SSMS并连接到数据库,然后运行两次控制台应用程序,则第二次控制台应用程序中的ExecuteReader显著更快。
请注意,您不必在SSMS中运行或甚至打开存储过程,只需连接到数据库即可。
通过打开且连接到相同数据库的SSMS,第二次运行控制台应用程序受到了显着影响和改善。 例如:
ExecuteReader when SSMS is not open 300 ms
ExecuteReader when SSMS is not open 300 ms
ExecuteReader when SSMS is not open 300 ms
Open SSMS and connect to database
First ExecuteReader when SSMS is open and connected to same database 300 ms
Second ExecuteReader with SSMS open and connected 10 ms !!!
Third ExecuteReader with SSMS open and connected 10 ms
Fourth ExecuteReader with SSMS open and connected 10 ms
Close SSMS
ExecuteReader back to reporting 300 ms to execute

换句话说,ExecuteReader报告的时间比存储过程实际运行的时间要少。

请注意,存储过程的运行时间始终相同。

看起来SSMS有一种缓存机制,允许控制台应用程序使用。

有人可以解释一下吗?sys.dm_exec_connections显示所有不同连接之间没有差异。

SSMS是v17.3,连接到SQL Server 2008 R2 SP2数据库。


你是在一个运行中打开SSMS测试的吗?还是在不同的运行中进行的? - Ferhat Sayan
抱歉,我不太明白你的意思。控制台应用程序打开连接,运行存储过程并退出。在打开 SSMS 之前和第一次运行之前,每次运行都是一致的。此后,行为再次保持一致,但与打开 SSMS 之前不同。 - user2849221
1
这很可能与连接池有关。您可以通过创建另一个仅连接到相同数据库的应用程序并“关闭”该连接来重现它,这意味着连接将返回到池中但仍然打开。 - CodeCaster
@CodeCaster,SSMS和控制台应用程序将在不同的应用程序域中运行,因此将有单独的连接池。 - Dan Guzman
@Dan 我也这么认为(不能很快地找到文档),但是否有某种低级连接池位于特定于应用程序域的池下面呢? - CodeCaster
显示剩余7条评论
2个回答

4
请确保数据库中未设置AUTO_CLOSE。根据聊天记录中的讨论,似乎已经将其设置为ON。
引用自微软的内容如下:(点此查看)

当设置了AUTO_CLOSE为ON时,由于每次连接后需要打开和关闭数据库,会导致频繁访问的数据库性能下降。AUTO_CLOSE还会在每次连接后清除过程缓存。

最佳实践建议

如果一个数据库被频繁访问,请将AUTO_CLOSE选项设置为OFF。

您可以通过运行以下查询关闭AUTO_CLOSE(正如Dan Guzman所建议的)。
ALTER DATABASE YourDB SET AUTO_CLOSE OFF;

1
只是确认一下:当 autoclose 设置为 false 时,控制台应用程序的第一次运行报告了 ExecuteQuery 的 300 毫秒,但无论 SSMS 是否打开,之后都只有 10 毫秒。 - user2849221
@user2849221,这可能是由于标准数据缓存造成的。SQL Server首次需要从存储中读取数据。随后的数据访问将来自内存,除非缓冲区被更近期的请求重用。 - Dan Guzman

0

2
我已经在ExecuteQuery之前、之后以及之前和之后放置了ClearAllPools,但没有任何明显的影响。 - user2849221

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接