Стратегия предотвращения OutOfMemoryException во время ETL в .NET

Я написал процесс ETL, который выполняет процесс ETL. Процесс ETL должен обработать более 100+ миллионов строк в целом для записей за 2 года. Чтобы избежать проблем с нехваткой памяти, мы разбиваем загрузку данных на каждые 7 дней. Для каждого процесса фрагмента он загружает все необходимые справочные данные, затем процесс открывает соединение sql и загружает исходные данные один за другим, преобразует их и записывает в хранилище данных.

Недостаток обработки данных по частям заключается в том, что она медленная.

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

Существуют ли какие-либо другие стратегии, которые я могу использовать, чтобы избежать OutOfMemoryException?

Например, локальная база данных, запись эталонных данных в файлы, создание другого процесса .NET для хранения большего объема памяти в Windows, использование хранимой процедуры CLR для выполнения ETL...

Среда: 32-битная ОС Windows 7. 4 ГБ оперативной памяти. Стандартный выпуск SQL Server.

Единственное решение — использовать процедуру хранения и позволить SQL Server обрабатывать ETL. Однако я стараюсь этого избегать, потому что программа также должна поддерживать Oracle. Другое улучшение производительности, которое я пробовал, — это добавленные индексы для улучшения загрузки запросов. Создайте собственный класс доступа к данным, чтобы загружать только необходимые столбцы, а не всю строку в память.

Спасибо


person dsum    schedule 28.04.2011    source источник
comment
Одним из вариантов является создание кэша фиксированного размера эталонных данных. Когда вашей программе нужны справочные данные, она ищет их в кеше. Если его там нет, он загружает его с вашего SQL-сервера. Это работает эффективно только в том случае, если в справочных данных есть локальность.   -  person Spike Gronim    schedule 28.04.2011


Ответы (3)


Не зная, как именно вы обрабатываете данные, сложно сказать, но наивное решение, которое можно реализовать в любом случае, — это использовать 64-битную ОС и скомпилировать ваше приложение как 64-битное. В 32-битном режиме куча .NET вырастет примерно до 1,5 ГБ, что может вас ограничивать.

person Can Gencer    schedule 28.04.2011
comment
Для уверенности! Безусловно, лучшая отдача от затраченных средств — это перейти на 64-разрядную систему и, возможно, даже удвоить объем памяти. Стоимость попытки спроектировать решение в небольшом пространстве памяти намного больше, чем потратить несколько долларов на 8 или 16 ГБ ОЗУ. - person Keith Bluestone; 28.04.2011
comment
Я тестировал на 64-битной версии, и это наверняка решает проблему. К сожалению, ограничение на клиентской машине. Они работают только с 32-битной ОС. Мне нужно будет поговорить с ИТ-отделом, чтобы узнать, возможно ли обновление до 64-битной ОС. - person dsum; 29.04.2011

Я знаю его старый пост, но для людей, которые ищут лучшие точки для написания операций с данными с языками программирования.

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

Одно из таких предложений, параллельные каналы данных. Здесь каждый канал будет выполнять ETL для отдельных фрагментов на основе разделения данных из источника. Например, вы можете параллельно рассматривать процессы нереста для данных за разные недели. Это по-прежнему не решит ваши проблемы с памятью в рамках одного процесса. Хотя может использоваться в случае, если вы достигли предела с выделением памяти в куче в рамках одного процесса. Это также полезно для чтения данных параллельно с произвольным доступом. Однако для координации и завершения процесса как единой операции ETL потребуется главный процесс.

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

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

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

Алгоритм объединения слиянием: идеально, когда источник уже отсортирован по ключу атрибута соединения. Ключевая идея алгоритма сортировки-слияния состоит в том, чтобы сначала отсортировать отношения по атрибуту соединения, чтобы чередующиеся линейные сканирования встречали эти наборы одновременно. Пример кода: https://en.wikipedia.org/wiki/Sort-merge_join

Вложенное соединение: работает как вложенный цикл, где каждое значение индекса внешнего цикла принимается в качестве предела (или начальной точки или чего-либо применимого) для индекса внутреннего цикла, и соответствующие действия выполняются над оператором (ами). ) после внутреннего цикла. Таким образом, если внешний цикл выполняется R раз, а для каждого такого выполнения внутренний цикл выполняется S раз, то общая стоимость или временная сложность вложенного цикла составляет O (RS).

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

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

Еще одна очень затратная операция — обратная запись в базу данных. Может возникнуть тенденция обрабатывать извлечение, преобразование и загрузку по одной строке за раз. Подумайте об операциях, которые можно векторизовать, где вы можете выполнять их вместе с операциями со структурами данных в большом количестве. Например, лямбда-операция над многомерным вектором вместо того, чтобы зацикливать каждую строку по одной за раз и выполнять преобразование и операции по всем столбцам для данной строки. Затем мы можем записать этот вектор в файл или базу данных. Это позволит избежать нагрузки на память.

person Sunil Soceite Generale    schedule 30.10.2018

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

В конце концов, я написал хранимую процедуру SQL, используя Merge для обработки процесса ETL для типа данных, который занимал слишком много времени для обработки приложения C#. Кроме того, бизнес-требования были изменены таким образом, что мы отказались от поддержки Oracle и поддерживали только 64-разрядный сервер, что снизило затраты на обслуживание и позволило избежать проблем с нехваткой памяти ETL.

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

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

Наконец, мы реализовали кеши (ключ, значение), чтобы часто используемые данные в диапазоне дат ETL загружались в память, чтобы уменьшить количество запросов к базе данных.

person dsum    schedule 01.11.2018