2012-05-25 2 views
3

У меня есть приложение, используемое для импорта большого массива данных (миллионы записей) из одной базы данных в другую, делая diff в этом процессе (IE удаляет все, что было удалено, и т.д). Из-за многих ограничений внешнего ключа и тому подобного и для ускорения обработки приложения он загружает всю базу данных назначения в память, а затем пытается загрузить части исходной базы данных и выполняет сравнение в памяти, обновляет назначения в памяти. В конце он записывает эти изменения обратно в пункт назначения. Базы данных не совпадают друг с другом, поэтому одна таблица в одном может быть несколькими таблицами в другом и т. Д.Передача больших объемов данных между доменами приложений быстро

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

Чтобы ускорить процесс отладки, я делаю архитектурные изменения, перемещая код импорта в отдельную dll, загружаемую в отдельный appdomain, чтобы мы могли ее выгружать, вносить изменения и перезагрузите его и попробуйте снова запустить раздел импорта, заглянув туда, где мы остановились, и посмотрим, получим ли мы лучшие результаты. Я думал, что я был гением, когда придумал этот план :) Но у него есть проблема. Я либо должен загрузить все данные из целевой базы данных во второй appdomain, а затем, прежде чем выгружать, скопируйте все это в первый, используя сделку [Serializable] (это действительно очень медленно при разгрузке и перезагрузке dll) или загрузка данные в хосте appdomain и ссылаться на него во втором, используя MarshalByRefObject (который, как оказалось, весь процесс замедляется)

Итак, мой вопрос: как мне это сделать быстро? Вроде, минутная макс! Я хотел бы просто скопировать данные, как будто это было просто передано по ссылке и не нужно делать полную копию.

Мне было интересно, есть ли лучший способ реализовать это, чтобы данные могли быть лучше разделены между двумя или, по крайней мере, быстро прошли между ними. Я искал и нашел вещи, рекомендующие использовать базу данных (мы загружаем данные в память, чтобы ИЗБЕГАЙТЕ базу данных), или вещи, которые просто говорят, чтобы использовать MarshalByRefObject. Я бы хотел сделать что-то легкое, но на самом деле это еще не сработало.

Я где-то читал, что загрузка DLL C++ или неуправляемой dll приведет к игнорированию доменов приложений и может привести к некоторым проблемам. В любом случае я могу использовать это в свою пользу, IE, загружать неуправляемую dll, которая содержит мой список для меня или что-то еще, и использовать его, чтобы обмануть мое приложение в использовании той же самой памяти для обеих областей приложения, чтобы списки просто зависали, когда Я выгружаю другую dll, выгружая домен приложения?

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

+0

Интересный вопрос. Но, не является ли код под каким-то испытательным покрытием (даже на высоком уровне)? Вы никогда не должны ждать * этого * долго, когда отлаживаете, ради бога. Я всего лишь для того, чтобы ускорить все как можно больше, заметьте, но тот факт, что вам приходится тратить много драгоценного времени, как только что-то пойдет наперекосяк, должно позвонить в колокольчик. Мне любопытно, каковы будут фактические ответы, хотя :) –

ответ

3

Подход приложений доменов - это хороший способ разделения для загрузки и выгрузки только части вашего приложения. К сожалению, как вы обнаружили, обмен данными между двумя доменами приложений непросто/быстро. Это похоже на два разных системных процесса, пытающихся установить связь, которая будет всегда медленнее, чем одно и то же сообщение процесса. Таким образом, путь - это использовать быстрый механизм взаимодействия между процессами. Пропустите WCF по мере того, как накладные расходы на рекламу вам здесь не нужны. Используйте named pipes, через который вы можете быстро передавать данные. Я использовал его раньше с хорошими результатами. Чтобы пойти еще быстрее, вы можете попробовать MemoryMappedFile (link), но это сложнее реализовать. Начните с именованных каналов, и если это слишком медленно, перейдите к файлам с отображением памяти.

Даже при использовании быстрого способа отправки вы можете столкнуться с еще одним узким местом - сериализации данных. Для больших объемов данных стандартная сериализация (даже двоичная) выполняется очень медленно. Вы можете посмотреть на protocol buffers.

Одно слово предостережения на AppDomain - любое неперехваченное исключение в одном из доменов приложений приводит к сбою всего процесса. К сожалению, они не разделены.

На боковой ноте. Я не знаю, что делает ваше приложение, но миллионы записей не кажутся чрезмерными. Может быть, есть место для оптимизации?

-1

Вы не сказали, если это был SQL Server, но вы использовали для этого SSIS? Есть, очевидно, some techniques, что позволяет быстро работать с большими данными.

Смежные вопросы