OutOfMemoryError при чтении одного столбца из PostgreSQL [дубликат]

10
задан Philip Couling 19 May 2012 в 08:56
поделиться

4 ответа

Попробуйте отключить автоматическую фиксацию:

// make sure autocommit is off
connection.setAutoCommit(false);

 st = connection.createStatement();
 st.setFetchSize(1000);
 System.out.println("start query ");
 rs = st.executeQuery(queryString);
 System.out.println("done query");

Ссылка

21
ответ дан dogbane 21 August 2018 в 23:55
поделиться
  • 1
    В точку. setFetchSize не работает в режиме autoCommit с драйвером PostgresQL JDBC. – Danubian Sailor 19 June 2012 в 11:10
  • 2
    Стоит отметить, что вам, вероятно, нужно снова включить автообновление, прежде чем закрывать соединение, если вы используете пул соединений, а другие части приложения полагаются на автообновление. В противном случае вы можете получить случайную потерю данных, если они явно не выполняются. – Matt Ball 23 July 2012 в 17:57
  • 3
    Более подробную информацию об этом ограничении JDBC PostgreSQL можно найти в jdbc.postgresql.org/documentation/head/… . – Alex 8 October 2014 в 16:15
  • 4
    FWIW autoCommit имеет значение & quot; on & quot; по умолчанию, поэтому обязательно отключайте его ... см. также другие комментарии. – rogerdpack 18 August 2017 в 20:33

Два запроса имеют совершенно разные вещи.

Использование предложения LIMIT ограничивает размер результирующего набора равным 10000, а при установке размера выборки нет, вместо этого он дает подсказку драйверу указав, сколько строк будет выбрано за раз при повторении через результирующий набор - который включает все строки 800k.

Таким образом, при использовании setFetchSize база данных создает полный набор результатов, поэтому он занимает очень много времени.

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

3
ответ дан Henning 21 August 2018 в 23:55
поделиться
  • 1
    Но он не выполняет через результирующий набор. Идея состоит в том, что while выполняет итерацию по набору результатов, в идеале она должна получать 1000 результатов по сети, затем вы можете обрабатывать их, а когда вы доберетесь до 1001-го, она будет получать следующие 1000 и т. Д. , – Jon Skeet 23 September 2009 в 22:11
  • 2
    Конечно. Разница в скорости связана с различными размерами наборов результатов, 10000 против 800000. – Henning 23 September 2009 в 22:38

Это будет зависеть от вашего драйвера. Из документов:

Дает драйверу JDBC подсказку о количестве строк, которые должны быть извлечены из базы данных, когда требуется больше строк. Количество указанных строк влияет только на результирующие наборы, созданные с использованием этого оператора. Если заданное значение равно нулю, подсказка игнорируется. Значение по умолчанию равно нулю.

Обратите внимание, что он говорит «подсказку» - я бы сказал, что это означает, что водитель может игнорировать намек, если он действительно хочет ... и это звучит вот что происходит.

2
ответ дан Jon Skeet 21 August 2018 в 23:55
поделиться
  • 1
    Да, я читал это, но не мог поверить, что JDBC + postgreSQL проигнорирует это, он существует целую вечность. – kresjer 23 September 2009 в 20:17
  • 2
    @kresjer: его postgresql, поэтому у вас должен быть доступ к источнику для DB и JDBC-драйверов. Вы можете использовать его, чтобы выяснить, что на самом деле происходит ... – Stephen C 23 September 2009 в 23:24
  • 3
    NB, что postgres (если autocommit выключен, так что размер выборки работает вообще), установив размер выборки в 0, очевидно, делает кеш-память «все». по умолчанию (предположим, что они интерпретируют «игнорирование» подсказки) с оракулом, по умолчанию 10 явно docs.oracle.com/cd/A97335_02/apps.102/a83724/resltse5.htm – rogerdpack 22 January 2015 в 01:24

Я заметил, что ваше использование API отличается от того, что выражается Javadoc:

Попробуйте передать параметры в этом порядке

  ResultSet.TYPE_FORWARD_ONLY,
  ResultSet.CONCUR_READ_ONLY,
  ResultSet.FETCH_FORWARD
2
ответ дан Vivek 21 August 2018 в 23:55
поделиться
  • 1
    Эти 3 клавиши вместе с настройкой conn.setAutoCommit (false) сделали трюк для меня – Peter 28 January 2015 в 23:57
Другие вопросы по тегам:

Похожие вопросы: