【问题标题】:why is a console app affected by having SSMS open为什么打开 SSMS 会影响控制台应用程序
【发布时间】:2018-01-15 21:51:41
【问题描述】:

我有一个控制台应用程序 (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 的情况下运行了测试?还是不同的运行方式?
  • 对不起,我不太明白你的意思。控制台应用程序打开一个连接,运行存储过程并退出。在打开 SSMS 之前和打开 SSMS 后的第一次运行时,每次运行都是一致的。此后行为再次一致,但与打开 SSMS 之前不同
  • 这很可能与连接池有关。您可以通过创建另一个仅连接到同一数据库然后“关闭”该连接的应用程序来重现它,这意味着该连接将返回到池中但仍处于打开状态。
  • 关闭 SSMS 控制台应用程序是否立即返回 300ms?
  • @CodeCaster、SSMS 和控制台应用程序将在不同的应用程序域中运行,因此会有单独的连接池。

标签: c# .net sql-server


【解决方案1】:

请确保您没有为您的数据库设置AUTO_CLOSE。根据chat 中的讨论,这似乎确实设置为ON。

Quoted from Microsoft

[当] AUTO_CLOSE 设置为 ON [它] 可能会导致性能下降 频繁访问的数据库,因为增加的开销 每次连接后打开和关闭数据库。 AUTO_CLOSE 每次连接后也会刷新过程缓存。

最佳实践建议

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

您可以通过运行以下查询来关闭AUTO_CLOSE(如Dan Guzman 所建议的那样):

ALTER DATABASE YourDB SET AUTO_CLOSE OFF;

【讨论】:

  • 只是为了确认:在自动关闭设置为 false 的情况下,控制台应用程序的第一次运行报告了 ExecuteQuery 的 300 毫秒,但此后 10 毫秒,无论 SSMS 是否打开
  • @user2849221,这可能是由于标准数据缓存。 SQL Server 最初需要从存储中读取数据。除非缓冲区被最近的请求重用,否则后续数据访问将来自内存。
【解决方案2】:

我希望这种行为来自Connection Pool Feature。 您能否在控制台应用程序中每次调用后尝试SqlConnection.ClearAllPools

【讨论】:

  • 我在 ExecuteQuery 之前、之后、之前和之后放置了 ClearAllPools,没有任何明显的影响。
猜你喜欢
  • 1970-01-01
  • 2010-10-29
  • 2010-10-05
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-28
相关资源
最近更新 更多