【问题标题】:.NET access to SQL over network is faster than locally - um, why?.NET 通过网络访问 SQL 比本地访问要快 - 嗯,为什么?
【发布时间】:2017-09-26 08:15:25
【问题描述】:

我有一个不寻常的问题,我的一台服务器的性能比其他所有服务器都好,我想知道原因 - 这样我就可以让其他服务器也能正常工作:-)

这是我的(简化的)场景: 我有一个 SQL Server 2012 机器,它是我们的生产环境——我们称之为 PROD。我有一个我们创建的 .NET 工具,它一遍又一遍地运行一些查询。如果我在与本地数据库通信的服务器上运行此工具,则对于一组简单查询,我的响应时间在 4 到 20 毫秒之间,对于更复杂的查询,响应时间在 589 到 731 毫秒之间。

我们还有另一个相同规格的 SQL Server 2012 机器 - 我们称之为 STAG。如果我在这个盒子上运行相同的工具,连接到 PROD 数据库(即相同的代码、相同的连接字符串等),对于简单查询,我得到的响应时间在 0 到 1 毫秒之间,对于更复杂的查询,响应时间在 109 到 133 毫秒之间,即明显更好。

我们有第三个相同规格的 SQL Server 2012 机器 - 我们称之为 TEST。同样,运行连接到 PROD 的相同工具,我得到的响应时间分别在 4 到 15 毫秒和 600 到 800 毫秒之间。

事实上,如果我在除我们的 STAG 环境之外的任何服务器(或客户端)上运行此工具,则时间大致相同。只是 STAG 的表现优于所有其他环境,我真的很想知道为什么!

如果我在 SSMS 中运行查询,那么它们都是高性能的(即非常快)。

因此,在大多数机器上,从 .NET 访问数据库似乎都有开销,除了我们的 STAG 服务器,我希望我们所有的服务器都具有这种性能水平。

我检查过的所有内容似乎都匹配:

  • SQL 客户端和服务器协议和配置
  • 底层硬件(都在同一个 vSphere 基础架构上运行)
  • .NET Framework 版本
  • 已应用 AV 版本和策略

我不知道还要检查什么 - 其他人可以提出任何建议吗?

谢谢

标记

【问题讨论】:

  • 分析一下。我的意思是,实际上分析它,而不是比较设置或假设事情应该相同。使用 Wireshark 跟踪网络流量并查看数据包延迟、SET STATISTICS TIME ON、查询计划。首先要做的是确定差异是由于 SQL Server 中的查询执行,还是由于底层网络/CPU/内存基础设施。我的钱是后者。 (虚拟硬件也是硬件,它的行为可能比物理硬件更奇怪。)
  • 我也倾向于同意你的观点,因为在 SSMS 中使用你上面提到的设置运行相同的查询,它与 SQL Server 无关,需要 0 毫秒 - 你不能比这更快!此外,从 STAG 服务器到 PROD 的访问速度要快得多这一事实告诉我,这与 .NET 本身有关,因为查询数据库的其他方式正在快速减轻。我会看看 wireshark 的东西,但服务器与自身通信比其他服务器慢的事实也似乎很奇怪。
  • 使用 Wireshark,我可以看到 TEST 服务器的数据发送和接收比 STAG 慢大约 30 毫秒,这对我来说表明 PROD 服务器的网络和底层硬件不是问题 -它必须介于运行的代码行和网络上的消息传递之间 - 也许在 .NET System.Data.SqlClient 内部?但这不就是一个供我们使用的黑匣子吗?
  • 如果您所说的“黑匣子”是指不仅容易反编译而且具有source online 的东西,那么是的,它完全是一个黑匣子。 :-P 但是,这里没有什么意义,因为我可以保证那里没有神奇的 30 毫秒延迟循环——它会尽可能地发送数据包。查看其他网络流量是否受到类似影响。尝试从一个简单的 .NET 应用程序执行一个简单的 HTTP 调用,检查软件防火墙,尝试netsh winsock reset 以获得咯咯笑声。
  • 我的意思是,这不仅仅是一个 30 毫秒的延迟 - 对于一个复杂的查询,差异是一台服务器上的 429 毫秒(与本地数据库通信的服务器)和另一台服务器上的 80 毫秒(与远程数据库)。本地到本地比远程到本地慢 5 倍。

标签: .net sql-server performance sqlclient


【解决方案1】:

是的 - 我终于找到了这个,它不是很好,但至少我有一致性。 我们计算时间的工具的逻辑有错误 - 我们使用 TimeSpan.TicksPerMillisecond 并且由于某种原因,我们的一台服务器上的 Stopwatch.Frequency 不同 8-@

切换到 Stopwatch.StartNew(),然后 Stop() 并使用 ElapsedMilliseconds 给我们正确的答案。

感谢 Jeroen 提供的所有帮助 - 至少在下次遇到性能问题时,我可以采纳您的建议并首先使用这些建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 2013-08-10
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2015-03-21
    • 1970-01-01
    相关资源
    最近更新 更多