Почему мои курсоры JDBC работают так медленно?

Я дословно следую коду, описанному на этой странице (пример 5.2).

Мой запрос довольно прост

SELECT * FROM "LSERAW", WHERE "DATETIME">='Sat 01 января 00:00:00 EST 2011' и "DATETIME"‹='Thu 30 Jun 00:00:00 EST 2011' ORDER BY "DATETIME" LIMIT 10000000

База данных проиндексирована на DATETIME. Однако, когда я увеличиваю LIMIT с 10 миллионов до 100 миллионов, моему коду требуется очень много времени для входа в цикл while. В 10 миллионов это очень быстро. Я думал, что при использовании курсоров цикл while всегда должен начинаться своевременно. Я делаю что-то не так с моим кодом?

Базовой базой данных является PostgreSQL для Windows.


person deltanovember    schedule 10.08.2011    source источник


Ответы (2)


Для автофиксации JDBC Connection установлено значение true. Драйвер сначала загружает весь набор результатов в ОЗУ.

Измените autocommit на false, и он вернется гораздо быстрее.

person Will Hartung    schedule 10.08.2011
comment
У меня есть следующая строка conn.setAutoCommit(false); как на примере - person deltanovember; 10.08.2011

ИСХОДНАЯ ПОПЫТКА (вероятно, неправильная, см. правки ниже): я не эксперт по курсорам, но я почти уверен, что использование курсора не означает, что инструкция SELECT вернется сразу же. Сервер все еще должен выполнить его, как и любой другой запрос, что может занять время. Я рекомендую попытаться выяснить, какая часть системы блокирует.

После того, как программа Java «зависнет», запустите SELECT * FROM pg_stat_activity с помощью отдельного клиента базы данных (например, psql). Если вы видите свой запрос в списке, это означает, что сервер все еще обрабатывает его.

Вы также можете изменить log_min_duration_statement сервера PostgreSQL на (например) 1000. Затем, после перезапуска PostgreSQL (или с помощью pg_ctl reload или чего-то подобного), снова запустите программу. После завершения запроса вы должны увидеть строку в файле журнала PostgreSQL, указывающую, сколько времени это заняло.

Удачи!


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

[Запросу] потребовалось несколько секунд, чтобы вернуться, и это создало негативный начальный опыт для пользователя. Что я узнал с тех пор, так это то, что мне нужно было просто применить некоторые настройки среды.

Они здесь:

set enable_sort = off
set enable_seqscan = off

Вы можете посмотреть это. Они просто предотвращают попытки PostgreSQL выполнить сортировку файлов, слияние файлов или последовательное сканирование, если присутствует какой-либо индекс. Теперь вне курсора вы все равно получите значительную задержку, потому что все строки будут доставлены в любом случае. Должна существовать методика подкачки на стороне клиента, иначе сервер не сможет доставлять данные по частям. Капис?

Но внутри курсора все вышеперечисленное работает очень хорошо. Почти мгновенно.

На самом деле у меня нет таблиц со 100 миллионами строк, поэтому я не могу это проверить. Но вы можете попробовать.


EDIT 2: раздел 11.4 руководства по PostgreSQL объясняет, почему именно enable_sort имеет такое большое значение:

Важным особым случаем является ORDER BY в сочетании с LIMIT n: явная сортировка должна будет обработать все данные, чтобы идентифицировать первые n строк, но если есть индекс, соответствующий ORDER BY, первый n строк можно получить напрямую, вообще не сканируя остальные.

person Matt Solnit    schedule 15.08.2011