Обработка очень большого количества данных в MyBatis - PullRequest
10 голосов
/ 01 июля 2011

Моя цель - сбросить все данные базы данных в файл XML. База данных не очень большая, около 300 МБ. Проблема в том, что у меня ограничение памяти 256 МБ (только в JVM). Очевидно, я не могу просто прочитать все в память.

Мне удалось решить эту проблему с помощью iBatis (да, я имею в виду iBatis, а не myBatis), вызвав его getList(... int skip, int max) несколько раз с увеличенным значением skip. Это решает мою проблему с памятью, но скорость меня не впечатляет. Имена переменных говорят о том, что метод скрытно выполняет весь набор результатов, пропуская затем указанную запись. Это звучит довольно избыточно для меня (я не говорю, что это то, что делает метод, я просто предполагаю основание на имени переменной).

Теперь я переключился на myBatis 3 для следующей версии моего приложения. Мой вопрос: есть ли лучший способ обрабатывать большие объемы данных в чанках в myBatis? Есть ли способ заставить myBatis обрабатывать первые N записей, возвращать их вызывающей стороне, оставляя соединение с результирующим набором открытым, чтобы в следующий раз, когда пользователь вызовет getList (...), он начнет читать из записи N + 1, не выполняя никаких действий? "пропуск"?

Ответы [ 4 ]

16 голосов
/ 02 ноября 2011

myBatis МОЖЕТ стримировать результаты.Что вам нужно, это пользовательский обработчик результатов.При этом вы можете взять каждую строку отдельно и записать ее в свой XML-файл.Общая схема выглядит следующим образом:

session.select(
    "mappedStatementThatFindsYourObjects",
    parametersForStatement,
    resultHandler);

Где resultHandler - это экземпляр класса, реализующего интерфейс ResultHandler.Этот интерфейс имеет только один метод handleResult.Этот метод предоставляет вам объект ResultContext.Из этого контекста вы можете извлечь строку, которая в данный момент читается, и что-то с ней сделать.

handleResult(ResultContext context) {
  Object result = context.getResultObject();
  doSomething(result);
}
7 голосов
/ 11 июля 2011

Нет, mybatis не имеет полной возможности потоковой передачи результатов пока .

РЕДАКТИРОВАТЬ 1: Если вам не нужны вложенные отображения результатов, вы можете реализоватьпользовательский обработчик результатов для потоковой передачи результатов.на текущие выпущенные версии MyBatis.(3.1.1) Текущее ограничение - это когда вам нужно сделать сложное отображение результатов.NestedResultSetHandler не допускает пользовательских обработчиков результатов.Исправление доступно, и похоже, что в настоящее время предназначено для 3.2.См. Выпуск 577 .

В целом, для потоковой передачи больших наборов результатов с помощью MyBatis вам потребуется.

  1. Реализация собственного ResultSetHandler .
  2. Увеличить размер выборки.(как отмечено ниже Гийомом Перро)
  3. Для вложенных карт результатов используйте исправление, обсуждаемое в Issue 577 .Это исправление также устраняет некоторые проблемы с памятью с большими наборами результатов.
2 голосов
/ 05 июля 2014

handleResult получает столько записей, сколько получает запрос, без паузы.

Когда слишком много записей для обработки, я использовал sqlSessionFactory.getSession (). GetConnection ().Затем, как обычный JDBC, получите Statement, получите Resultset и обработайте одну за другой записи.Не забудьте закрыть сессию.

0 голосов
/ 24 августа 2017

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

sql может быть что-то вроде:

SELECT * FROM resource 
    WHERE "ID" >= continuation_id LIMIT 300;

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

...