Обработка больших наборов данных с помощью LINQ

Если Вы используете runtime/totalMemory решение, которое было отправлено во многих ответах здесь (я сделал это много), несомненно, вызовут две сборки "мусора" сначала, если Вы хотите довольно точные/последовательные результаты.

Для effiency Java обычно позволяет мусору заполнять всю память прежде, чем вызвать GC, и даже тогда это обычно не полный GC, таким образом, Ваши результаты для runtime.freeMemory () всегда быть где-нибудь между "реальной" суммой свободной памяти и 0.

первый GC не получает все, он получает максимум от него.

подъем состоит в том, что, если Вы просто делаете freeMemory () вызов, Вы получите число, которое абсолютно бесполезно и значительно различается, но если делают 2 gc, первые, это - очень надежный индикатор. Это также делает стандартную программу НАМНОГО медленнее (секунды, возможно).

6
задан Nestor 10 November 2009 в 03:03
поделиться

4 ответа

You are putting pressure on the data context to generate the query from scratch every time.

Try using a compiled query instead.

6
ответ дан 10 December 2019 в 00:40
поделиться

Вы обращаетесь к базе данных дважды для каждой итерации цикла - один раз для получения строки, а затем еще раз для обновления строки. Это не очень эффективно.

Вы должны работать пакетами:

  • Получите набор строк вперед, выбрав диапазон, а не одно значение, например 0–100 для первого пакета, 101–200 для следующего пакета и т. Д. . Это будет быстрее всего, если у вас есть кластерный индекс, определенный в столбце Code.

  • Создайте контекст данных до входа в цикл

  • Внутри цикла просто обновите объекты

  • Вызов SubmitChanges () ПОСЛЕ того, как цикл будет завершено, это отправит все обновления в базу данных в одном соединении / транзакции

  • Повторите для следующего пакета

Вы должны сделать размер пакета настраиваемым, так как вы не можете быть уверены, какой размер пакета обеспечит наилучшую производительность - не надо t жестко закодируйте его в приложение.

Кроме того, я бы использовал SingleOrDefault () с проверкой нуля вместо Single (), если вы не можете гарантировать, что всегда будет строка для любого значения i.

EDIT:

Что касается памяти использование, это намного сложнее контролировать, но это не свойственно LINQ to SQL, любой алгоритм пакетной обработки должен иметь дело с этим. Хотя я не рекомендую использовать GC.Collect () на практике, обычно этого достаточно в качестве обходного пути после обработки большого пакета.

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

3
ответ дан 10 December 2019 в 00:40
поделиться

Мне не удалось воспроизвести проблему. Использование памяти было плоским. Низкая производительность, но постоянная память.

Вы уверены, что не протекает где-то еще? Можете ли вы создать минимальный образец кода, который воспроизводит проблему?

Редактировать:

Я использовал практически тот же образец кода:

for (int ii = 1; ii < 200000; ii++)
{
    using (var dc = new PlayDataContext())
    {
        var record = 
            (from r in dc.T1s where r.Id == ii select r).SingleOrDefault();
        if (record != null)
        {
            record.Name = "S";
            dc.SubmitChanges();
        }
    }
}

без проблем.

Итак, что нужно исключить:

  • Версия Framework. Я на последнем.
  • DataContext / сложность сущности. Моя тестовая таблица состоит всего из двух полей: Id (int) и Name (nvarchar (max)).

Можете ли вы воспроизвести проблему с последней версией FW с небольшим примером DataContext?

1
ответ дан 10 December 2019 в 00:40
поделиться

вы можете попробовать поместить создание контекста данных вне цикла for, хотя не знаете, сколько памяти это сэкономит вам.

Может быть, вы можете вызвать GC .Collect () после каждого цикла, проверьте, можете ли вы вызвать сборку мусора вручную.

0
ответ дан 10 December 2019 в 00:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: