2011-07-19 160 views
3

我有一些代码将数据从数据库中提取出来,然后做一个简单的比较来检查记录是否匹配特定的模块和响应,然后使用计数和显示统计信息。不幸的是,当数据库中的任何记录超过1000条时,它会非常缓慢。优化foreach循环

在nHibernate中,我打开了懒惰加载,这在初始查询时间中有点帮助,但是当它到达这个部分时,它需要深入一点才会减慢很多。我想问题是它从很多不同的表中提取数据来获得这些统计数据。

从一些研究看来,我应该能够通过编写linq语句而不是使用foreach循环来加速这一过程,但是我已经尝试了几次,而且我没有走得太远。我想知道是否有人能帮助我指出正确的方向。或者对一个很好的Linq教程或书籍,因为我对这个主题知之甚少

另外我看到在类似的情况下,人们已经建议把一个工作放入sql server来填充另一个用于查找的表,但我想如果可能的话避免这一点

这是代码。

int modules = 0; 
var sessionsWithPullHits = from session in m_sessions where session.PullHits.Count > 0 select session; 

foreach (ISession<PullHitRecord, PushHitRecord> session in sessionsWithPullHits) 
{ 
    foreach (var pullHit in session.PullHits) 

    if ((pullHit.Module == _Module) && (pullHit.Response == _response)) 
    { 
     modules++; 
    } 
} 

非常感谢任何帮助的人可以给。

+1

顺便说一句,写得很好的问题。欢迎来到stackoverflow! –

回答

4

LINQ:

var modules = (from session in m_sessions 
       from pullHit in session.PullHits 
       where pullHit.Module == _Module && pullHit.Response == _response 
       select pullHit).Count(); 

注意,我不知道如何将其转化为SQL,但它是一个LINQ语句,所以应该工作。

+0

感谢您的帮助,这完全适用于更换foreach循环。我想我可能需要去下创建一个单独的表的性能只在foreach循环轻微上升的路线。 – Neil

+0

nconsider我的建议 - 有可能你的c#代码不是低效率的部分。请看看你的数据库代码。 –

1

如果你所要做的只是获得会话计数,你可能会更好地将_Module和_response传递给SP,并让DB进行计数,只返回计数。

当然,如果你做的更多,这是不适用的。但是回报很多你不愿意使用的东西;使用效率不高。

2

@George达克特的答案是当场就与LINQ更换的foreach代码。或者,你可以表达他用流利的语法相同的查询,像这样:

var modules = m_sessions 
.SelectMany(session => session.PullHits, 
      (session, pullHits) => new { pullHits = pullHits }) 
.Where(session => session.pullHits.Module == _Module && 
        session.pullHits.Response == _response) 
.Count(); 

这是不那么漂亮,但由此产生的IL较小,可能会给你稍微更好的结果。此外,这个版本仍然会提供稍小的代码,可能会带来小的收益。测试看看:

var modules = m_sessions 
    .Select(session => session.PullHits 
     .Count(pullHit => pullHit.Module == _Module && 
         pullHit.Response == _response)) 
    .Sum(); 

免责声明:我不支持过早的优化,我只启用它:-)

0

我想看看你的表管理指数。添加一个索引中加入使用的列可以对性能有显着的影响。看到这个reference

下面是其他SQL性能调整技巧的列表:Performance Tuning SQL Server Joins