更新:
我想象这可以提高性能的原因有两个方面:
> sql Server不需要重置连接状态.我认为这是相当可观的改善.
>减少网络延迟,因为客户端不需要发送一个exec sp_reset_connection,等待响应,然后发送任何真正要执行的sql.
第二个好处是我感兴趣的,因为在我的架构中,客户端有时距离数据库有一些距离.如果每个sql批处理或rpc都需要双向往返,这会使任何网络延迟的影响加倍.消除这种双重呼叫可能会提高性能.
是的,我可以做很多其他的事情来提高性能,如重新构建应用程序,我是解决问题根本原因的大粉丝,但在这种情况下,我只想知道是否可以防止sp_reset_connection被称为.那么我可以测试是否有任何性能改进,并适当地评估不称之为的风险.
这提示另一个问题:与sp_reset_connection的网络通信是否真的发生如上所述?即客户端发送exec sp_reset_connection,然后发送真正的sql?还是一切都在一个块?
解决方法
我猜,微软意识到(正如有人通过实验here),打开门来避免重置,比获得(可能)小的性能增益要危险得多.不能说我责怪他们.
Does the client send
exec sp_reset_connection
,wait for a response,then send the real sql?
编辑:我错了 – 见here – 答案是否定的.
摘要:在TDS消息中设置了一个特殊位,指定连接应该被重置,sql Server会自动执行sp_reset_connection.它在Profiler中显示为单独的批次,并且将始终在要执行的实际查询之前执行,因此我的测试无效.
是的,它是单独发送的.
我组装了一个小C#测试程序来证明这一点,因为我很好奇:
using System.Data.sqlClient; (...) private void Form1_Load(object sender,EventArgs e) { sqlConnectionStringBuilder csb = new sqlConnectionStringBuilder(); csb.DataSource = @"MyInstanceName"; csb.IntegratedSecurity = true; csb.InitialCatalog = "master"; csb.ApplicationName = "blarg"; for (int i = 0; i < 2; i++) _RunQuery(csb); } private void _RunQuery(sqlConnectionStringBuilder csb) { using (sqlConnection conn = new sqlConnection(csb.ToString())) { conn.Open(); sqlCommand cmd = new sqlCommand("WAITFOR DELAY '00:00:05'",conn); cmd.ExecuteNonQuery(); } }
启动Profiler并将其附加到您选择的实例,然后根据我提供的虚拟应用程序名称进行过滤.然后,在cmd.ExecuteNonQuery()上放置一个断点;行并运行程序.
第一次跳过,只是查询运行,所有你得到的是在等待5秒后的sql:BatchCompleted事件.当断点第二次击中时,您在分析器中看到的只是一个事件.当您再次重试时,您会立即看到exec sp_reset_connection事件,然后在延迟之后显示sql:BatchCompleted事件.
去除exec sp_reset_connection调用(这可能或可能不是您的合法性能问题)的唯一方法是关闭.NET的连接池.如果您打算这样做,您可能希望建立自己的连接池机制,因为只需将其关闭并且不做任何事情,可能会比打入额外的往返更多地受伤,而您将拥有手动处理正确性问题.