Foreach через сгруппированные результаты linq невероятно медленный, какие-нибудь советы?

Я выполнил профилирование программы, которую запускаю, и больше всего времени занимает получение результатов из запроса linq:

var Results = 
    from a in Table
    group a by a.Value into b
    select new {Group = b};

foreach(var Result in Results)
{
    //Do calcs
}

Любые идеи о том, как я могу ускорить это?


person sooprise    schedule 17.09.2010    source источник
comment
Я не думаю, что здесь достаточно информации. Что такое Таблица? Он делает вызовы базы данных? Что занимает много времени? Просто цикл foreach? Или что в foreach?   -  person Bryan    schedule 18.09.2010
comment
Похоже, что select new {Group = b} может быть просто select b, но это не ускорит процесс.   -  person Henk Holterman    schedule 18.09.2010
comment
Группировка может быть дорогостоящей операцией. Если таблица находится в базе данных, есть ли у нее индекс по значению?   -  person Henk Holterman    schedule 18.09.2010
comment
Таблица — это таблица в базе данных SQL, и да, у нее есть индекс по значению. Влияет ли наличие индекса на производительность?   -  person sooprise    schedule 18.09.2010
comment
да, но в хорошем смысле (при извлечении)   -  person Kirk Woll    schedule 18.09.2010


Ответы (3)


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

Если вы хотите сохранить результаты запроса в results, чтобы они уже были рассчитаны к моменту запуска цикла foreach, добавьте вызов ToList().

var results = 
    (from a in Table
     group a by a.Value into b
     select new {Group = b}).ToList();
person Mark Byers    schedule 17.09.2010
comment
Но сделает ли это (весь опубликованный код) быстрее? - person Henk Holterman; 18.09.2010
comment
Сомневаюсь, но для уверенности надо мерить. Что он будет делать, так это заранее брать затраты на выполнение, чтобы итерация была быстрее. Мне кажется, что OP беспокоился больше о том, что итерация была удивительно медленной, а не о том, что общее время выполнения кода было медленным. Если вы не уверены, что происходит за кулисами, вы можете ожидать, что первая строка будет медленной, а цикл — быстрым. - person Mark Byers; 18.09.2010
comment
У меня есть список из 128000 элементов. Сгруппировал по productid. Сделал куда по ключу и побежал хоть что. Это заняло 0,10 сек. После выполнения ToList в IEnumerable‹IGrouping‹T, T›› время составило 0,0002 сек. Не знаю, что происходит за экраном. Но это делает большие различия. - person mimo; 18.09.2013

Если вы используете .NET 4, посмотрите P-LINQ или Parallel ForEach. Это должно резко повысить производительность.

Не могу точно сказать, основываясь на предоставленной информации, но может быть SQL-запрос занимает слишком много времени?

Если узким местом действительно является цикл ForEach, то Parallel ForEach будет лучшим выбором.

person Steve Danner    schedule 17.09.2010
comment
Если это связано с вводом-выводом (база данных), несколько дополнительных потоков не сильно помогут. Я думаю, это зависит (от недоступных деталей). - person Henk Holterman; 18.09.2010
comment
Это будет иметь только потенциальное улучшение для LINQ to Objects, но если здесь используется IQueryable‹T›, это не поможет (сильно), так как узкое место, вероятно, находится в бэкэнде. - person Reed Copsey; 18.09.2010
comment
@ Рид, да, как сказал Хенк, это полностью основано на недоступных деталях. Если проблема заключается в выполнении вычислений в цикле foreach, это поможет, или даже если инструкция LINQ направлена ​​против коллекции объектов, но мы не знаем этого из предоставленной информации. - person Steve Danner; 18.09.2010

У меня была такая же проблема только с 2000 записями Sqlite (индексированными), используемыми для MSChart, по-видимому, это вызвано тем, что оператор группы LINQ запрашивает все записи.

Единственное решение, которое я нашел, состояло в том, чтобы вернуться к собственному SQL, и диаграмма отображалась мгновенно, а не за 2 секунды с использованием LINQ с SQlite.

person peterincumbria    schedule 03.01.2012