Прочитайте 3 миллиона записей в спящем режиме

1

Я новичок в спящем режиме, и мне нужно прочитать 2 миллиона записей из базы данных z/OS DB2 с гибернацией в Java. (JDBC)

Моя проблема в том, что я запускаю OutOfMemory после 150000 записей.

Я слышал о пакете и т.д., Но я только нахожу решения для фактической вставки новых записей. Что я хочу сделать, так это прочитать эти записи в ArrayList для дальнейшего использования.

Поэтому я фактически просто выбираю одну строку базы данных для уменьшения данных:

getEntityManager().createQuery("select t.myNumber from myTable t").getResultList();

Также было бы интересно, если есть лучший способ прочитать такое огромное количество записей. (Может быть, без Hibernate?)

  • 2
    Вы не можете, скорее, не должны загружать столько записей в память. Вы должны сделать это в партии, т.е. загрузить партию 100 (зависит) и обработать ее, а затем взять следующие 100.
  • 0
    Попробуйте прочитать на Apache Solr
Показать ещё 1 комментарий
Теги:
select
hibernate

6 ответов

4
Лучший ответ

Ниже приведен способ выполнения пакетной обработки с использованием спящего режима. Имейте в виду, что это не проверено на 100%. Это своего рода псевдо-логика.

int i=0;
int batch = 100;
List<myNumber> numList = getEntityManager().createQuery("select t.myNumber from myTable t").setFirstResult(i).setMaxResults(batch).getResultList();

while(numList.size() == batch){
    //process numList
    i+=batch;
    numList = getEntityManager().createQuery("select t.myNumber from myTable t").setFirstResult(i).setMaxResults(batch).getResultList();    
}

Документация Hibernate для setFirstResult() и setMaxResults()

1

Вы не должны загружать все записи в память, но обрабатывать их в пакетном режиме, например: цикл каждые 1000 записей с помощью createQuery (...). SetFirstResult (i * 1000).setMaxResults(1000);

0

Лучшим подходом является использование statelessSession (без операции с кешем) и массовые операции с помощью метода scrollableResults:

StatelessSession statelessSession = sessionFactory.openStatelessSession(connection);
    try {
     ScrollableResults scrollableResults = statelessSession.createQuery("from Entity").scroll(ScrollMode.FORWARD_ONLY);

     int count = 0;
     while (scrollableResults.next()) {
      if (++count > 0 && count % 100 == 0) {
       System.out.println("Fetched " + count + " entities");
      }
      Entity entity = (Entity) scrollableResults.get()[0];
      //Process and write result
     }
    } finally {
     statelessSession.close();
    }
0

Вы нашли верхний предел своей кучи. Посмотрите здесь, чтобы знать, как правильно вычесть кучу:

Увеличить размер кучи в Java

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

0

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

0

Это в основном вопрос дизайна для проблемы, над которой вы работаете. Забудьте Hibernate, даже если вы делаете то же самое в простом JDBC, вы столкнетесь с проблемой памяти, возможно, немного опоздаете. Идея загрузки таких огромных данных и хранения в памяти не подходит для приложений, требующих коротких циклов запроса-ответа, и также не подходит для масштабируемости. Как и другие, вы можете попробовать поведение партии или пейджинга, или если вы хотите быть более экзотичным, вы можете попробовать параллельную обработку через распределенную сетку данных (например, Infinispan) или каркас-сокращение от Hadoop.

Идя по описанию вашей проблемы, кажется, что вам нужно хранить данные в памяти. Если вы должны хранить огромные данные в памяти, вы можете запросить данные в пакетах и сохранить их в распределенном кеше (например, Infinispan), который может охватывать несколько JVM на одной машине или на нескольких машинах, образующих кластер. Таким образом, ваши данные будут частично размещаться на каждом узле. Здесь Infinispan может использоваться как распределенный кеш.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню