2017-02-21 5 views
5

У меня есть код, как это ниже,resultSet.next(): извлекает ли данные из буфера или из базы данных?

try (Connection connection = this.getDataSource().getConnection(); 
     PreparedStatement statement = connection.prepareStatement(sqlQuery);) { 


     try { 
      statement.setFetchSize(10000); // Set fetch size 
      resultSet = statement.executeQuery(); 

      while (true) { 
       resultSet.setFetchSize(10000); 
       boolean more = resultSet.next(); 
       if (! more) { 
        break; 
       } 
       // populating an arraylist from the value from resultSet 
      } 
     } 
     catch (Exception e) { 
      LOGGER.error("Exception : "+e); 
     } 
    } catch (SQLException e) { 
     LOGGER.error("Exception : "+e); 
    } 

Мое понимание заключается в следующем,

Оператор размер выборки 10000. когда statement.executeQuery() выполняется, она возвращает ResultSet курсор. Он будет иметь 10000 строк в памяти. Когда вызывается resultSet.next, он получает одну строку из буфера памяти. (одна строка за вызов). Когда в памяти больше нет строк, запрос снова запускается, и 10000 строк снова извлекаются из базы данных и сохраняются в буфере. Это продолжается до тех пор, пока ни одна строка будет выбираемые из БД

Так что, если я правильно понимаю, сколько реальных БД вызывает будет там для полных строк 210000? Это 21? (210000/10000)

Также, когда и кто вызывает БД (когда строки в буфере все прочитаны), чтобы получить больше строк (10000, в моем случае) и сохранить в буфере. Также когда очищается буфер?

Пожалуйста, исправьте меня, если я ошибаюсь в своем понимании.

Мне нужно работать с миллионами данных в Oracle Database.

Спасибо за любые советы/Информация

С уважением,

SD

+0

Метод 'setFetchSize #' должен быть подсказкой. Это полностью зависит от драйвера JDBC, чтобы использовать или игнорировать его. Также 'who call the DB' -> драйвер делает это. Получил большую часть этого из этого [SO Q/A] (http://stackoverflow.com/questions/1318354/what-does-statement-setfetchsizensize-method-really-do-in-sql-server-jdbc-driv) –

+0

В случае драйвера OCI есть раздел в документации, в котором описывается объем сетевых поездок по сети для каждого вызова OCI. Драйвер JDBC не документирован таким образом - он обеспечивает API более высокого уровня. Но вы можете использовать документ OCI как введение в тему. – ibre5041

ответ

3

Единственные люди, которые могут ответить на ваш вопрос, являются авторами драйвера Oracle JDBC.

Это означает, что вызов db для чтения следующего фрагмента данных не займет больше нескольких мс (или меньше), основная часть времени будет зависеть от скорости передачи и, возможно, от того, как вы получите данные из набора результатов.

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

Об очистке буфера, в основном это область сбора мусора, после того, как вы потеряете ссылку на набор результатов.

Просто убедитесь, что ваше заявление FORWARD ONLY, как по соображениям производительности, так и по памяти.

connection.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);

+0

полезная ссылка: [Oracle JDBC Documentation] (https://docs.oracle.com/cd/E11882_01/java.112/e16548/resltset.htm#JJDBC28621) – Izruo

+0

Размер выборки> 1K, вероятно, не так сильно отличается , Если вы хотите увидеть, что происходит со стороны базы данных, вы можете включить трассировку SQL. – BobC

4

Извините, но ваше понимание является неправильным. Нет такой вещи, как «запрос увольняется снова».

Выполнение запроса выполняется один раз. Для обработки запроса потребуется начальный промежуток времени (что вы не можете сделать ничего, кроме оптимизации вашего запроса), а затем он начнет создавать строки на сервере, которые должны быть переданы клиенту. Пока строки передаются, сервер, вероятно, будет продолжать генерировать больше строк, которые будут переданы, и буферизировать их на сервере. Эта буферизация на стороне сервера полностью не связана с буферизацией, о которой мы говорим в этом Q & A, и вы очень мало контролируете ее. (Возможно, с помощью конфигурации сервера, если это вообще возможно.) В какой-то момент все строки будут собраны на сервере, и тогда единственной оставшейся задачей будет передача оставшихся строк с сервера клиенту.

Таким образом, насколько клиент может сказать, как только он отправил запрос на сервер, задержка сервера пока задумывается, после чего строки становятся доступными со скоростью, которая обычно равна быстро, поскольку провод может нести их. Таким образом, клиент начинает читать эти строки с resultSet.next().

Без какой-либо буферизации каждый звонок resultSet.next() отправил бы запрос от клиента на сервер, сообщив ему отправить следующую строку, и сервер ответит только этой строкой. Это дало бы первую строку очень быстро, но в долгосрочной перспективе это было бы очень неэффективно, потому что это вызвало бы слишком много круговых поездок между клиентом и сервером.

С буферизацией первый звонок resultSet.next() запросит кучу строк с сервера. Это наложит штраф на время получения первой строки, потому что вам придется ждать 100 строк, которые будут отправляться по проводу, но в конечном итоге это значительно сократит общие сетевые издержки, потому что будет только один раунд между клиентом и сервером на каждую строку.

Идеальная стратегия для resultSet.setFetchSize() заключается в том, чтобы оставить ее такой, какой она есть, и не слишком беспокоиться об этом.

Но если вы параноик в отношении производительности, то хорошей стратегией было бы начать с довольно небольшого размера выборки (скажем, 10), чтобы быстро получить свой первый ряд, а затем удвоить его до тех пор, пока он не достигнет определенный максимум (скажем, 100), за которым нет никакого улучшения.

+0

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

+0

@GordThompson Ну, вот что я имел в виду. Я просто предполагаю, что это работает, потому что это не терпит неудачу, когда OP его использует. Я, конечно, ошибаюсь. Я бы предположил, что это зависит от реализации РСУБД, но я не смотрел на стандарт. Но что-то говорит мне, что ваш вопрос риторический. Почему бы вам просто не указать, что вы знаете, поэтому я могу исправить этот последний абзац? –

+0

@GordThompson Разрешается изменение размера выборки для открытого курсора. Независимо от того, поддерживает ли драйвер JDBC или просто игнорирует его, определяется ли реализация. –

Смежные вопросы