优化foreach循环

本文关键字:循环 foreach 优化 | 更新日期: 2023-09-27 18:02:26

我有一些代码,从数据库中取出记录,然后我做一个简单的比较,检查记录是否匹配特定的模块和响应,然后使用计数并显示统计数据。不幸的是,当数据库中的记录超过1000条时,它非常慢。

在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++;
    }
}

优化foreach循环

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语句,所以应该工作

@George Duckett的答案是用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();

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

如果您想做的只是获得会话计数,那么最好将_Module和_response传递给SP,让DB进行计数,只返回计数。

当然,如果你做的更多,这是不适用的。但是,返回大量不使用的单词是没有效率的。

我会考虑管理您的表上的索引。向连接中使用的列添加索引可以对性能产生显著影响。

这里是其他SQL性能调优技巧的列表: