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

cke*_*rth 7 c# sql-server sql-server-2005 .net-4.0 linq-to-sql

我有一个遗留的.Net 4项目(名称为"A"),它使用Linq-to-SQL查询数据库,我有另一个.Net 4项目(命名为"B"),其中包含类似但不同的查询代码与"A"相同的数据库.

两个项目:

  • 是C#项目{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
  • 使用相同的程序集(版本v4.0.30319,相同的文件夹)
    • System.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实例看起来都很相似.db服务器进程的sql句柄包含相同的SQL语句.但是"A"抛出超时异常并且"B"在几秒钟内执行 - 重复!

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

确切地说:如果查询由于原因而运行"慢" - 重复 - 同一个查询如何运行得更快只是因为它被另一个Linq-to-SQL代码调用?

(还有)我不知道的副作用吗?是否有一些DataContext的实例值我必须特别关注运行时?

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

为了完整起见,我将以下示例链接到:

请记住,我不能透露完整的数据库模式,也不能透露我要查询的代码和实际数据.(SQL表在命名的列旁边有其他列,而C#代码有点复杂,因为Linq查询是有条件构造的.)

更新 - 在运行时更深入了解

两个DataContext实例的一些属性:

Log = null;
Transaction = null;
CommandTimeout = 60;
Connection: System.Data.SqlClient.SqlConnection;
Run Code Online (Sandbox Code Playgroud)

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

"Data Source=server;Initial Catalog=sourceDb;Persist Security Info=True;User ID=user;Password=password"
Run Code Online (Sandbox Code Playgroud)

没有运行显式SqlCommands来将SET选项传递给数据库会话.两者都不包含内联TVF SET选项.

Zer*_*er0 10

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

在极少数情况下,您要告诉我两个SELECT语句完全相同但性能差异很大,我几乎可以肯定它们在不同的事务隔离级别下运行.即使您没有明确创建任何SQL命令,单个SQL命令也是隐式事务.

如果由于某种原因跟踪不清楚,您应该发布正在运行的命令及其指标.

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

  • 包括“审核登录”事件并包括 TextData 列。这将揭示(我认为的)一堆“隐形”SET 设置。比较和对比两个查询使用的连接。 (2认同)

Nav*_*eet 0

我想你会在你的“A”项目 edmx-file 中检查 LazyLoadingEnabled="true" 。

如果 LazyLoadingEnabled="true":在延迟加载的情况下,相关对象(子对象)在被请求之前不会自动与其父对象一起加载。默认 LINQ 支持延迟加载。

IF LazyLoadingEnabled="false":在急切加载的情况下,相关对象(子对象)将与其父对象一起自动加载。要使用预加载,您需要使用 Include() 方法。