Java JDBC Lazy-Loaded ResultSet
Есть ли способ получить ResultSet, который вы получаете при запуске JDBC-запроса, для ленивой загрузки? Я хочу, чтобы каждая строка загружалась так, как я ее запрашиваю, а не заранее.
5 ответов
Короткий ответ:
использование Statement.setFetchSize(1)
перед звонком executeQuery()
,
Длинный ответ:
Это очень сильно зависит от того, какой драйвер JDBC вы используете. Возможно, вы захотите взглянуть на эту страницу, которая описывает поведение MySQL, Oracle, SQL Server и DB2.
Основные вынос:
- Каждая база данных (т.е. каждый драйвер JDBC) имеет свое поведение по умолчанию.
- Некоторые водители будут уважать
setFetchSize()
без каких-либо предостережений, в то время как другие требуют некоторой "помощи".
MySQL - это особенно странный случай. Смотрите эту статью. Похоже, если вы звоните setFetchSize(Integer.MIN_VALUE)
затем он будет загружать строки по одной за раз, но это не совсем понятно.
Другой пример: вот документация по поведению PostgreSQL. Если автоматическая фиксация включена, ResultSet будет извлекать все строки одновременно, но если она отключена, вы можете использовать setFetchSize()
как и ожидалось.
И последнее, что нужно иметь в виду: эти настройки драйвера JDBC влияют только на то, что происходит на стороне клиента. Сервер может по-прежнему загружать весь набор результатов в память, но вы можете контролировать, как клиент загружает результаты.
Не могли бы вы добиться этого, установив размер выборки для вашего оператора в 1?
Если вы выбираете только 1 строку за раз, каждая строка не должна загружаться до тех пор, пока вы не вызовете next() в ResultSet.
например
Statement statement = connection.createStatement();
statement.setFetchSize(1);
ResultSet resultSet = statement.executeQuery("SELECT .....");
while (resultSet.next())
{
// process results. each call to next() should fetch the next row
}
Здесь есть ответ.
Цитата:
Драйвер JDBC Presto никогда не буферизует весь набор результатов в памяти. Серверный API возвращает не более ~1 МБ данных драйверу за запрос. Драйвер не будет запрашивать больше данных с сервера, пока эти данные не будут использованы (вызывая
next()
метод на ResultSet соответствующее количество раз).Из-за того, как работает серверный API, размер выборки драйвера игнорируется (согласно спецификации JDBC, это только подсказка).
Докажи, чтоsetFetchSize
игнорируется
Я думаю, что вы хотели бы отложить фактическую загрузку самого ResultSet. Вы должны будете реализовать это вручную.
Вы найдете это намного проще, используя спящий режим. В основном вам придется свернуть свои собственные, если вы используете jdbc напрямую.
Стратегии извлечения в hibernate легко настраиваются и, скорее всего, предложат варианты производительности, о которых вы даже не знали.