为什么在linq中将.ToList()耗费给实体?

Mem*_*eak 1 c# linq asp.net-mvc linq-to-entities

我们有一个使用linq实体的网站,我们发现它最近很慢,经过故障排除后,我发现每当我们使用linq实体从数据库中搜索数据时,它会消耗很多CPU时间,就像toList()功能一样.我知道这可能是因为我们在数据库中有大量数据会导致响应变慢,但我只是想知道是否还有其他可能导致此问题的原因?

我该怎么做才能优化这类问题?以下是可能的原因:

  1. ToList() 可能会加载所有对象的外来对象(外键),如何强制它只加载对象?

  2. 我的连接池太小了吗?

如果还有其他可能的原因,请告诉我,并指出正确的方向来解决这个问题.

Amy*_*y B 5

在Linq中 - 查询在枚举查询时将查询结果从一系列操作返回到源.

IQueryable<Customer> myQuery = ...

foreach(Customer c in myQuery)  //enumerating the query causes it to be executed
{

}

List<Customer> customers = myQuery.ToList();
  // ToList will enumerate the query, and put the results in a list.
  // enumerating the query causes it to be executed.
Run Code Online (Sandbox Code Playgroud)

执行查询需要一些东西(没有特定的顺序)

  • 从池中提取数据库连接.
  • 查询由查询提供程序解释(在这种情况下,提供程序是实体的linq,解释是某种形式的sql)
  • 解释后的表单将传输到数据库,在那里它执行它所做的工作并返回数据对象.
  • 必须生成一些方法将传入的数据对象转换为所需的查询输出.
  • 数据库连接将返回到池中.
  • 所需的查询输出可能会在返回到您的代码之前对其进行状态跟踪.

此外,数据库有几个步骤,这里是从查询sql server的角度列出的:

  • 接收查询文本并根据现有计划的查询计划缓存进行检查.
  • 如果不存在任何计划,则会创建一个新计划并由查询优化程序粘贴到计划缓存中.
  • 执行查询计划 - IO/locks/CPU/Memory - 其中任何一个都可能成为瓶颈
  • 返回查询结果 - 网络可能是瓶颈,特别是如果结果集很大.

所以 - 要找出查询问题所在,你需要开始测量.我会按照我检查的顺序订购这些目标.这不是一个完整的列表.

  1. 获取查询的已翻译的sql文本.您可以使用sql server profiler.您可以使用调试器.有很多方法可以解决这个问题.确保查询文本返回对象所需的内容,不多也不少.确保查询的表符合您的期望.运行查询几次.

  2. 查看结果集.这是合理的还是我们正在寻找500 Gigs的结果?当整个事情不需要时,是否会查询整个表格?是否意外地产生了笛卡尔结果?

  3. 获取查询的执行计划(在sql studio中,单击show estimated execution plan按钮).查询是否使用您期望的索引?该计划看起来很糟糕(可能是一个糟糕的计划来自缓存)?查询是否按照您期望的顺序在表上工作,并以您期望的方式执行嵌套/合并/散列连接?是否存在并行化,当查询不值得时(这是错误索引的标志/ IO的TONS)?

  4. 测量查询的IO.(在sql server中,发出SET STATISTICS IO ON).检查每个表的逻辑IO.哪张桌子突出?再次,查找表访问的错误顺序或可以支持查询的索引.

    如果你已经做到这一点,你很可能找到并解决了这个问题.我会继续,但万一你没有.

  5. 将查询的执行时间与枚举的执行时间进行比较.如果存在很大差异,则可能是解释数据对象的代码很慢或生成缓慢.也可能是查询的翻译需要一段时间.这些都是棘手的问题需要解决(在LinqToSql中我们使用编译的查询来解决它们).

  6. 测量代码运行的机器的内存和CPU.如果您受限,请使用代码分析器或内存分析器来识别并解决问题.

  7. 查看计算机上的网络统计信息,特别是您可能希望使用TCPView查看计算机上的TCP套接字连接.套接字资源可能被误用(例如在一分钟内打开和关闭数千个).

  8. 检查数据库以查找其他连接持有的锁.

我想这就够了.希望我没有忘记任何明显的事情要检查.