Оптимизация циклов foreach - PullRequest
3 голосов
/ 19 июля 2011

У меня есть некоторый код, который извлекает записи из базы данных, и затем я делаю простое сравнение, чтобы проверить, соответствуют ли записи конкретному модулю и ответу, а затем использую количество и отображение статистики.К сожалению, это очень медленно, когда он достигает чего-то большего, чем 1000 записей в базе данных.

В nHibernate я включил отложенную загрузку, которая немного помогла во время начального запроса, но когда он добирается до этой части, где онуглубиться немного глубже это сильно замедляет.Я предполагаю, что проблема в том, что он извлекает данные из множества различных таблиц для получения этой статистики.

Из некоторых исследований кажется, что я мог бы ускорить это, написав операторы linq вместо использования циклов foreach, ноУ меня было несколько попыток, и я не очень далеко.Мне было интересно, если кто-нибудь может помочь направить меня в правильном направлении.Или к хорошему учебнику или книге по Linq, так как я мало что знаю по теме

Также я видел, что в подобных случаях люди рекомендовали помещать работу на сервер sql, чтобы заполнить другую таблицу, которая используется для поиска, но я быЯ хотел бы избежать этого, если это возможно.

Вот код.

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

Большое спасибо за любую помощь, которую кто-то может оказать.

Ответы [ 4 ]

4 голосов
/ 19 июля 2011

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, поэтому он должен работать.

2 голосов
/ 19 июля 2011

@ Ответ Джорджа Дакетта за замену кода foreach на LINQ. Кроме того, вы можете выразить его тот же запрос в свободном синтаксисе, например, так:

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();

Отказ от ответственности: я не поддерживаю преждевременную оптимизацию, я только включаю ее :-)

1 голос
/ 19 июля 2011

Если все, что вы пытаетесь сделать, это получить счетчик сеансов, вам лучше передать _Module и _response в SP, и позволить DB выполнять подсчет, возвращая только счет.

Конечно, если вы делаете больше, это не применимо.Но возвращать многие записи, которые вы не используете, неэффективно.

0 голосов
/ 19 июля 2011

Я бы посмотрел на управление индексами на ваших столах. Добавление индекса к столбцу, используемому в объединении, может оказать значительное влияние на производительность. См. Это ссылка .

Вот список других советов по настройке производительности SQL: Настройка производительности соединений SQL Server

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...