在 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.
执行查询需要一些东西(没有特定顺序)
- 从池中提取数据库连接。
- 查询由查询提供程序解释(在这种情况下,提供程序是 linq 到实体,解释是某种形式的 sql)
- 解释后的表格被传输到数据库,在那里它会做它所做的事情并返回数据对象。
- 必须生成一些方法来将传入的数据对象转换为所需的查询输出。
- 数据库连接返回到池中。
- 所需的查询输出可能会在返回到您的代码之前对其进行状态跟踪。
另外,数据库还有几个步骤,这里从查询sql server的角度列出:
- 接收查询文本并针对现有计划的查询计划缓存进行检查。
- 如果不存在计划,则由查询优化器创建一个新计划并将其放入计划缓存中。
- 执行查询计划 - IO/locks/CPU/Memory - 其中任何一个都可能是瓶颈
- 返回查询结果 - 网络可能是瓶颈,特别是在结果集很大的情况下。
所以 - 要找出您的查询问题出在哪里,您需要开始测量。我将按照我检查它们的顺序对这些目标进行排序。这不是一个完整的列表。
获取查询的翻译后的 sql 文本。您可以为此使用 sql server profiler。您可以使用调试器。有很多方法可以解决它。确保查询文本返回您对对象的要求,不多不少。确保查询的表符合您的期望。运行查询几次。
查看结果集。这是合理的还是我们正在查看 500 Gigs 的结果?当不需要整张桌子时,是否查询了整张桌子?是否意外生成了笛卡尔结果?
获取查询的执行计划(在sql studio中,点击show estimated execution plan
按钮)。查询是否使用您期望的索引?该计划是否看起来很奇怪(可能来自缓存的错误计划)?查询是否按照您期望的顺序在表上工作,并以您期望的方式执行嵌套/合并/散列连接?当查询不值得时(这是错误索引/ IO TONS 的标志),是否有并行化开始?
测量查询的IO。(在 sql server 中,发出 SET STATISTICS IO ON)。检查每个表的逻辑 IO。哪张桌子脱颖而出?再次,查找错误的表访问顺序或可以支持查询的索引。
如果您已经做到了这一点,那么您可能已经发现并解决了问题。不过我会继续,以防你没有。
比较查询的执行时间和枚举的执行时间。如果存在很大差异,则可能是解释数据对象的代码很慢或者生成速度很慢。也可能是查询的翻译需要一段时间。这些都是需要解决的棘手问题(在 LinqToSql 中,我们使用编译查询来解决它们)。
测量运行代码的机器的内存和 CPU。如果您被限制在那里,请使用代码分析器或内存分析器来识别和解决问题。
查看机器上的网络统计信息,特别是您可能希望使用 TCPView 查看机器上的 TCP 套接字连接。套接字资源可能被误用(例如一分钟打开和关闭数千个)。
检查数据库中其他连接持有的锁。
我想这就够了。希望我没有忘记任何明显的事情要检查。