Большой ResultSet по запросу postgresql - PullRequest
4 голосов
/ 06 мая 2009

Я выполняю запрос к таблице в базе данных postgresql. База данных находится на удаленной машине. Таблица содержит около 30 вложенных таблиц, использующих возможность разбиения postgresql .

Запрос вернет большой набор результатов, около 1,8 млн. Строк.

В моем коде я использую поддержку Spring JDBC, метод JdbcTemplate.query , но мой RowCallbackHandler не вызывается.

Мое лучшее предположение заключается в том, что драйвер postgresql jdbc (я использую версию 8.3-603.jdbc4) накапливает результат в памяти перед вызовом моего кода. Я думал, что конфигурация fetchSize может это контролировать, но я попробовал, и ничего не изменилось. Я сделал это как руководство postgresql рекомендуется .

Этот запрос работал нормально, когда я использовал Oracle XE. Но я пытаюсь перейти на postgresql из-за функции разделения, которая недоступна в Oracle XE.

Мое окружение:

  • Postgresql 8,3
  • Windows Server 2008 Enterprise, 64-разрядная
  • JRE 1.6 64-бит
  • Пружина 2.5.6
  • Postgresql JDBC Driver 8.3-603

Ответы [ 4 ]

4 голосов
/ 06 мая 2009

Чтобы использовать курсор для извлечения данных, необходимо установить тип ResultSet для ResultSet.TYPE_FORWARD_ONLY (по умолчанию) и автоматически зафиксировать значение false в дополнение к установке размера выборки. Об этом говорится в документе, на который вы ссылались, но вы явно не упомянули, что сделали эти шаги.

Будьте осторожны со схемой разделения PostgreSQL. Он действительно делает ужасные вещи с оптимизатором и может вызвать серьезные проблемы с производительностью там, где их не должно быть (в зависимости от особенностей ваших данных). В любом случае, ваш ряд только 1.8M строк? Нет причин, по которым его нужно будет разбивать на основе одного размера, если он соответствующим образом проиндексирован.

2 голосов
/ 07 мая 2009

Свойство fetchSize работает, как описано в postgres manual .

Моя ошибка заключалась в том, что я устанавливал auto commit = false для соединения из пула соединений, которое не было соединением, используемым подготовленным оператором.

Спасибо за все отзывы.

2 голосов
/ 06 мая 2009

Могу поспорить, что нет ни одного клиента вашего приложения, которому нужно 1.8M строк одновременно. Вам следует подумать о разумном способе разбить результаты на более мелкие части и дать пользователям возможность перебирать их.

Это то, что делает Google. Когда вы выполняете поиск, могут быть миллионы просмотров, но они возвращают по 25 страниц за раз, полагая, что на первой странице вы найдете то, что вам нужно.

Если это не клиент, и результаты каким-то образом обрабатываются, я бы порекомендовал базе данных обойти все эти строки и просто вернуть результат. Нет смысла возвращать 1,8M строк только для вычисления на среднем уровне.

Если ни один из них не подходит, у вас есть реальная проблема. Время переосмыслить это.

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

Я бы порекомендовал переориентировать себя - начните думать об этом как о решении для отчетности.

0 голосов
/ 12 августа 2015

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

Я добавил это: @Transactional(readOnly = true)

Приветствия.

...