gpt4 book ai didi

c# - 为什么相同的 Linq-to-SQL 查询会在不同项目的数据库服务器上消耗更多的 CPU 时间?

转载 作者:太空狗 更新时间:2023-10-29 20:10:04 24 4
gpt4 key购买 nike

我有一个旧版 .Net 4 项目(将其命名为“A”),它使用 Linq-to-SQL 来查询数据库,并且我有 另一个 .Net 4 项目(将其命名为“B”),它具有类似但不同的代码,它查询与“A”相同的数据库。

两个项目:

  • 是 C# 项目 {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
  • 使用相同的程序集(版本 v4.0.30319,相同的文件夹)
    • 系统.dll
    • System.Data.dll
    • System.Data.Linq.dll

自动生成的 DataContext特定于每个项目,但以相同的方式实例化:

  • 使用 SQL 身份验证的相同连接字符串
  • 两个 DataContext 都设置了它们的 CommandTimeout从默认值到 60 秒
  • DataContext 的所有其他配置选项都是默认值

Linq 查询的构建方式对于项目而言并不完全相同,但生成的 Linq 查询是相同的。生成的 (T-)SQL select 语句也是一样的! (监控并验证数据库服务器上的 SQL 句柄)

数据库服务器是:

  • Microsoft SQL Server Enterprise 2005 x64 (9.00.4035.00)
  • 操作系统:Microsoft Server 2003 R2 SP2 x64

如果运行受监控的 CPU项目“A”的查询时间(在数据库服务器上)急剧增加,并抛出命令超时异常。(System.Data.SqlClient.SqlException:超时已过期)

另一方面,“B”的查询在 (大约 3 秒) 内执行。通过使用相同参数再次调用“A”的代码,我能够重现该行为(不更改代码或数据库)。“B”甚至在几秒钟内执行,同时“A”正在增加其 CPU 时间。

遗憾的是,在同事重新创建索引后,我无法再重现该行为。同一位同事提到查询在“上个月”运行得很快(尽管与“上个月”相比没有代码更改...)。

我调试了两个项目的代码 - 两个 DataContext 实例看起来很相似。数据库服务器进程的 sql 句柄包含相同的 SQL 语句。但是“A”抛出超时异常,“B”在几秒钟内执行 - 重复!

为什么相同的 Linq-to-SQL 查询在项目“A”的数据库服务器上消耗的 CPU 时间比项目“B”多得多?

准确地说:如果查询由于某些原因运行“缓慢”——重复——同一个查询如何运行得更快,仅仅因为它被另一个 Linq-to-SQL 代码调用?

会不会有我(还)不知道的副作用?是否有一些 DataContext 的实例值我必须专门查看运行时?

顺便说一句:SQL 语句 - 通过 SSMS - 确实在每次运行时使用相同的查询计划。

为了完整起见,我链接了一个示例:

  • C# code项目“B”的片段(两个项目的 SqlRequest.GetQuery 部分看起来很相似)
  • SQL file包含适当的数据库模式
  • 数据库execution plan

请记住,我不能透露完整的数据库模式、代码或我正在查询的实际数据。(SQL 表除了命名的列之外还有其他列,并且 C# 代码有点复杂,因为 Linq 查询是有条件地构造的。)

更新 - 在运行时获得更多洞察

两个 DataContext 实例的一些属性:

Log = null;
Transaction = null;
CommandTimeout = 60;
Connection: System.Data.SqlClient.SqlConnection;

SqlConnection 是从这样的连接字符串创建的(两种情况):

"Data Source=server;Initial Catalog=sourceDb;Persist Security Info=True;User ID=user;Password=password"

没有运行明确的 SqlCommands 来将 SET 选项传递给数据库 session 。都不包含内联 TVF SET 选项。

最佳答案

您需要在 SQL Server 上设置 run a trace,而不是从 C# 端调试它。这将向您显示 AB 在服务器上执行的所有内容。执行计划对你没有好处,因为它恰恰是 - 只是一个计划。您想要查看确切 语句及其实际 性能指标。

在极少数情况下,您会告诉我这两个 SELECT 语句完全相同但性能却大不相同,我几乎可以肯定它们在不同的 transaction isolation levels 下运行.单个 SQL 命令是一个隐式事务,即使您没有显式创建任何命令也是如此。

如果出于某种原因跟踪没有明确说明,您应该发布正在运行的命令及其指标。

注意:运行跟踪会产生一些性能开销成本,因此我会尽量保持较小的时间范围或尽可能在非高峰期运行。

关于c# - 为什么相同的 Linq-to-SQL 查询会在不同项目的数据库服务器上消耗更多的 CPU 时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25687391/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com