2009-05-18 2 views
1

У меня есть требование, когда я должен выбрать около 60 миллионов плюс записи из базы данных. После того, как у меня есть все записи в ResultSet, я должен сформировать некоторые столбцы в соответствии с требованиями клиента (формат даты и формат номера), а затем я должен записать все записи в файле (вторичная память).Лучший дизайн для сценария

  • В настоящее время я выбираю записи на основе дня (7 выбирает на 7 дней) из БД и помещает их в HashMap. Чтение из HashMap и формирование некоторых столбцов и, наконец, запись в файл (отдельный файл в течение 7 дней).
  • Наконец, я объединю все 7 файлов в одном файле.

  • Но весь этот процесс занимает 6 часов. Чтобы улучшить этот процесс, я создал 7 потоков в течение 7 дней, и все потоки записывают отдельные файлы.

  • И наконец, я объединю все 7 файлов в одном файле. Этот процесс занимает 2 часа. Но моя программа собирается OutOfMemory через 1 час и так далее.

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

Примечание: Клиент не хочет ничего менять в базе данных, например, создавать индексы или хранимые процедуры, они не хотят касаться базы данных. Спасибо заранее.

+0

Можете ли вы рассказать нам, что RDMS вы используете? Это повлияет на то, какие решения, ориентированные на базу данных, могут быть доступны. Кроме того, можете ли вы рассказать нам, предназначена ли база данных для обработки транзакций (высоко нормированная) или более аналитическая обработка (сильно денормализованная)? –

+0

Клиент не хочет ничего менять в БД. Они не готовы создавать новый индекс или SP или нормализовать таблицы. –

ответ

4

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

В зависимости от базы данных БД они могут иметь инструменты, которые помогут в этом, например, для SSIS для Sql Server 2005+.

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

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

В ADO.Net есть DataReader, который является прямым, только для чтения (Firehose) курсором набора результатов. Он возвращает данные по мере выполнения запроса. Это очень важно. По сути, моя логика была бы:

IDataReader reader=GetTheDataReader(dayOfWeek); 

while (reader.Read()) 
{ 
    file.Write(formatRow(reader)); 
} 

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

+0

, пожалуйста, предложите что-то на Java , Сторона JDBC. Они не хотят ничего менять на стороне БД, я знаю, что это сумасшествие :) :) –

+0

JDBC/ADO - это просто технологии доступа клиентов, также не требующие изменений в базе данных. Их не сумасшедшие они хотят сохранить свою БД в текущем состоянии - это важный бит, где находятся данные. Разумеется, JDBC имеет похожий только для чтения курсор только для чтения. – gbjbaanb

+0

Я бы предположил, что JDBC делает, я был бы потрясен, если это не так, поскольку это не совсем новая концепция. Ключ состоит в том, что курсор позволяет считывать результаты во время выполнения запроса.Я использовал это в шаблоне simillar, где я не знал, сколько результатов мне нужно, пока моя бизнес-логика не побежит (И логика была в основном выражением, определяемым пользователем, так что может быть что угодно). Использование datareader было огромным преимуществом, так как мы просто перестали читать, поскольку у нас было достаточно данных. – JoshBerke

0

Зависит от базы данных, которую вы используете, но если бы это был SQL Server, я бы рекомендовал использовать что-то вроде SSIS для этого, а не писать программу.

+0

Клиент не готов ничего изменить в базе данных. Нет индекса и хранимой процедуры. –

+0

Иногда вам нужно сказать клиенту, почему то, что они хотят, является плохой идеей, и лучший способ сделать что-то - внести изменения на уровне базы данных. Они не хотят, чтобы медленно работающее приложение блокировало свои таблицы. Пакет SSIS не изменит структуру базы данных или не добавит сохраненные процессы или индексы, но это один из лучших способов импорта или экспорта данных, поскольку он специально предназначен для этого. – HLGEM

+0

Как упоминалось в HLGEM, использование SSIS не требует каких-либо изменений в базе данных. Это просто инструмент для преобразования данных (именно это вы делаете). Предостережение заключается в том, что он работает только с SQL Server - поэтому, если они не используют SQL Server, то, конечно, SSIS не является вариантом (хотя могут быть похожие инструменты для любой используемой базы данных) –

2

Я думаю, что Джош предлагает это:

У вас есть петли, где вы в настоящее время проходите через все результирующие записи вашего запроса (только с помощью псевдокода здесь):

while (rec = getNextRec()) 
    { 
    put in hash ... 
    } 

for each rec in (hash) 
    { 
    format and save back in hash ... 
    } 

for each rec in (hash) 
    { 
    write to a file ... 
    } 

instead, do it like this: 

while (rec = getNextRec()) 
    { 
    format fields ... 
    write to the file ... 
    } 

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

1

Очевидно, что чтение 60 миллионов записей одновременно использует всю вашу память, поэтому вы не можете этого сделать. (т. е. ваша модель с 7 потоками). Чтение 60 миллионов записей по одному использует все ваше время - так что вы не можете этого сделать (например, ваше первоначальное чтение в файловую модель).

Итак, вам придется пойти на компромисс и сделать немного того и другого.

У Джоша есть это право - откройте курсор к вашей БД, который просто читает следующую запись, один за другим, самым простым, наиболее функциональным способом. Курсор «firehose» (иначе известный как только для чтения, только для прямого) - это то, что вы хотите здесь, поскольку оно накладывает наименьшую нагрузку на базу данных. БД не позволит вам обновлять записи или идти назад в наборе записей, чего вы не хотите, так что ему не нужно будет обрабатывать память для записей.

Теперь у вас есть этот курсор, вам дается одна запись за раз в БД - прочитайте ее и напишите в файл (или несколько файлов), это должно закончиться довольно быстро. Тогда ваша задача состоит в том, чтобы объединить файлы в 1 с правильным порядком, что относительно просто.

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

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

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