的LINQ to SQL:太多的CPU使用率:当有多个用户

问题描述:

我使用LINQ to SQL和看到我的CPU使用率天空rocketting会发生什么。看下面的截图。我有三个问题的LINQ to SQL:太多的CPU使用率:当有多个用户

  • 我该怎么做才能减少CPU使用率。我已经完成了分析并基本删除了所有内容。将每个LINQ to SQL语句转换为编译查询有帮助吗?

  • 我还发现,即使使用编译查询,ByID()等简单语句在3.25GB RAM 3.17GHz的服务器上可能需要3毫秒 - 这在功能不太强大的计算机上会变得更慢。或者编译后的查询速度越快,使用得越多?

  • 单个用户的CPU使用率(在本地服务器上达到12-15%)会与访问服务器的用户数相乘 - 当应用程序被置于实时服务器上时。即一次有2个用户将意味着15 * 2 = 30%的CPU使用率。如果是这样的话,那么我的应用程序一次最多只能有4-5个用户。或者不LINQ to SQL .net共享一些CPU使用率。 alt text http://www.freeimagehosting.net/uploads/5f10e1f694.png

+1

索引,索引,索引... – 2010-05-01 07:21:02

+1

您可以发布您认为是导致问题的查询的SQL吗? – 2010-05-01 07:44:28

+1

你的SQL Server在同一台机器上吗?你确定LINQ to SQL(.NET)在吃你的CPU,还是你的SQL Server? – Steven 2010-05-01 07:56:48

简介。简介。简介。

档案,以找出究竟哪些查询花费最多的资源,提高该查询的性能。您可以使用DataContext的Log属性查看SQL - 请参阅this article。您可以在SQL Server中获取查询的查询计划 - 请参阅this article。方式

例子来提高查询:

  • 添加缺少的索引。
  • 重写查询以利用已经存在的索引。
  • 不要为每个查询获取太多数据 - 使用分页并且只有在请求时才获取更多行。不要获取不需要的字段。
  • 不要为每个查询获取太少数据 - 不要一次一个循环获取一行。一次取多行。

一旦你这样做了,再次配置文件来检查你是否改进了该查询的性能。如果没有,重复,直到你有。

然后再配置文件,看看下一个杀手级的查询是什么,直到你的表现尚可重复上述过程。

你说你已经成型,但你还没有发布任何分析信息,如查询,查询计划,执行时间,查询频率,等等。没有更多分析数据,我们所能做的是猜测。

+0

索引什么? SQL服务器中的表。 LINQ to SQL甚至关心表上的索引 - 它不适用于这里http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/ad8cc0d5-e1a3-4333-b0a1-1d67c406a6c7 – soldieraman 2010-05-01 07:28:18

+0

@soldieraman: LINQ to SQL将查询表达式转换为SQL。 SQL服务器根据哪些索引可用并基于表的统计信息为这些SQL语句创建查询计划。您可以通过将某些内容分配给您的上下文的Log属性来记录发送到数据库的SQL语句。 – 2010-05-01 07:30:29

+1

LINQ参与数据库的索引与任何其他外部实体 - 最终用户,开发人员,ADO.NET,ODBC等相同。如果您已将索引创建为数据库模式的一部分,则LINQ将使用它们,因为您的数据库是已经设置好使用它们。 – 2010-05-01 07:33:29

编译查询不会“获得更快”与更多的使用。编译查询的主要好处是可以节省LINQ引擎在每次调用时重复执行翻译过程的需求。

至于CPU使用率,如果这是你的开发机,赔率是非常好的别的东西是怎么回事造成这种高活性。即使这是专用的数据库服务器,我也会强烈建议使用SQL Profiler来调查您的LINQ查询生成的语句。它可能需要调整您的模式,代码或数据库设置,以使用量回到更可接受的水平。

  1. 是否有任何可以缓存的常见查询?
  2. linq查询是否可以重写
  3. 大部分查询处理是在Web服务器上还是在SQL中完成?
  4. 你在同一个盒子上运行SQL服务器和Web服务器吗?你有一个模拟生产环境的测试环境吗?

我注意到在这里有一些应用程序的类似行为;使用ANTS Profiler,我们已经将我们的CPU利用率缩小到了Linq to SQL代码中。我们发现了几个主要的地方,这成为一个问题:

  1. 复杂的Linq到SQL查询。使用几个连接和where子句约束等。这些问题是Linq to SQL引擎必须将C#语句转换为SQL语句。我相信,如果相同的代码由相同的DataContext调用,那么默认情况下可以重新使用此转换,但是如果您为每次执行实例化新的DataContext,则每次都会执行CPU密集型转换代码。这可以通过用存储过程或使用预编译的Linq to SQL查询(Here's a blog post showing how to create a compiled query)将复杂的Linq替换为SQL查询来解决。
  2. 基于反射的属性分配。我们发现像DataContext.Orders.FirstOrDefault(o => o.OrderID = orderID)这样的简单查询可能非常耗费CPU资源,因为它们使用反射将所有属性设置为查询中返回的值。除此之外,我们尚未对此进行调查。我们简单地用一些手写代码将标准C#数据访问(例如SqlCommand,SqlClient)中的一些Linq代码替换为基于SQL的代码,以将适当的列数据拖入适当的属性中,但仅限于ANTS告诉我们的地方重要。进行此更改通常会明显降低CPU利用率(例如,从2000 ms的CPU利用率下降到39 ms)。
  3. 一般的Linq性能问题(并非Linq to SQL专用);虽然编写Linq查询确实比类似的迭代方法导致更多的意图揭示代码,但是我们发现有时查询最终会变得非常低效(通常通过多次迭代集合或构建笛卡儿式产品,而真正不必要的) 。我没有任何关于这个问题的例子,但是ANTS能够帮助找到这些问题(通常针对特定代码行寻找非常高的命中次数)。这些通常可以通过对Linq查询进行小的调整来解决(或者在某些情况下用几个语句替换Linq查询)。

也许值得注意的是,我们使用Linq to SQL是基于GUI创建的DBML文件,因此使用包含列映射等所有信息的属性装饰类。

这正是我们发现的有关Linq to SQL;我很想看看其他人的经历。我强烈推荐使用ANTS Performance Profiler来确定CPU利用率集中在应用程序中的哪个位置;请注意,如果CPU的高利用率是基于SQL的(它听起来不像是你的情况),那么ANTS可能不会有帮助(我的答案也不会)。

我们最近部署了一个使用linq到sql的大型电子商务应用程序,并且经历了与您描述的非常相似的CPU使用情况。

经过几周的分析和调试跟踪,结果证明恶棍是在运行时查询的jit编译。

我们浏览了我们的数据层并将所有查询转换为编译查询,并且当查询第一次被编译时,我们的CPU使用率从一个恒定的100%立即变为平均5%到20%,并且一些尖峰高达80%。