Установка размера Oracle для выборок строк выше делает мое приложение медленнее? - PullRequest
27 голосов
/ 10 февраля 2012

Как указано здесь и подтверждено здесь , число строк по умолчанию, которое Oracle возвращает в момент, когда запрашивает данные через JDBC, равно 10. Я работаю над приложением, которое должночитать и сравнивать много данных из нашей базы данных.Я думал, что если мы просто увеличим defaultRowPrefetch до 1000, то наше приложение будет работать быстрее.Как оказалось, он работал медленнее и примерно на 20%.

Затем мы решили просто медленно увеличить число с 10 и посмотреть, как оно работает.Мы увидели увеличение примерно на 10%, установив его где-то между 100 и 200. Однако я бы никогда не догадался, что установка этого значения заставит наше приложение работать медленнее.Есть идеи, почему это может произойти?

Спасибо!

РЕДАКТИРОВАТЬ:

Просто для пояснения, я использую Oracle 11g R2 и Java 6.

РЕДАКТИРОВАТЬ 2:

Хорошо, я хочу перефразировать мой вопрос, чтобы быть ясным, потому что, исходя из ответов ниже, я не выражаю себя должным образом:

Как возможно, что если я установлю более высокий размер выборки, мое приложение будет работать медленнее?Для меня это звучит как сказать: «Мы даем вам более быстрое подключение к Интернету, то есть более толстый канал, но ваш просмотр веб-страниц будет медленнее.

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

Ответы [ 6 ]

23 голосов
/ 16 февраля 2012

Возможные объяснения:

  1. Java ничего не делает, в то время как Oracle вычисляет первые 1000 строк вместо первых 10.

  2. Oracle ничего не делает, в то время как Java вычисляет последние 1000 строк вместо последних 10.

  3. Коммуникационные протоколы (например, TCP / IP) много ждут, а затем должны обрабатывать больше данных одновременно, но пиковая передача данных будет ограничена аппаратными ограничениями . Этому противостоят издержки протокола, поэтому должен быть оптимальный размер выборки, а все, что меньше или больше, будет медленнее;))

  4. Было бы хуже, если бы процесс выборки был синхронным с другим кодом Java, так что Java запрашивает больше строк только после обработки предыдущих данных , а Oracle в это время ничего не делает.

    Представьте, что есть 3 человека:

    • 1-й лист бумаги формата А4 пополам
    • 2-й доставляет стопки согнутой бумаги из одной комнаты в другую
    • 3-й вырезает какую-то форму из согнутой бумаги.

    Насколько большими должны быть стеки, если 1-й должен ждать, пока 2-й вернется, а 2-й должен дождаться, пока 3-й закончит свою работу?

    Стеки 1000 не будут лучше, чем стеки 10, я думаю;))

12 голосов
/ 14 февраля 2012

Как и все, нет настройки FAST=TRUE.Хотя размер выборки JDBC по умолчанию, равный 10, не идеален для вашей ситуации, он подходит для «типичного» OLTP-приложения и, на самом деле, не так уж и плох для вашего случая .Очевидно, большой размер выборки не идеален для вашей ситуации.Но опять же, это не , что плохо делать 1000 за один раз.

Другой фактор, который вы не упомянули, это как WIDE строки таковытянут.Учтите, что порция данных, которую вы извлекаете с сервера базы данных по сети на сервер приложений, равна sum(WIDTH*ROWS).Если ваши строки имеют ширину 5000 байт, а вы извлекаете 1000 за раз, то каждая выборка будет приносить 5 МБ данных.В другом случае, возможно, ваши строки "тощие" с шириной всего 100 байт.Тогда получение 1000 из них - это всего лишь 100 000 штук.

Поскольку только ВЫ можете знать, как будут выглядеть возвращаемые данные, рекомендуется установить размер выборки в масштабе всей системы для "общего" случая, а затем настроить индивидуальные запросы по мере необходимости.

В общем, я также нашел 100, чтобы быть лучшим параметром для больших процессов обработки данных.Это не рекомендация , а передача наблюдения.

6 голосов
/ 14 января 2013

Кстати, по крайней мере с Oracle вы должны быть осторожны с размером выборки, потому что драйвер Oracle выделяет массив для максимально возможный размер , взятый каждой строкой, а не фактический размер данных. Так что, если у вас толстая таблица, ваш след памяти может пострадать.

Взгляните сюда - http://www.oracle.com/technetwork/database/enterprise-edition/memory.pdf

В Oracle вы можете узнать максимально возможное пространство, занимаемое столбцом в таблице метаданных user_tab_columns (data_length). Может использоваться для определения размера выборки.

В грубых тестах я обнаружил, что 4 *1024* 1024 / сумма (data_length для всех столбцов вашей таблицы) - это разумный размер выборки.

6 голосов
/ 13 февраля 2012

Правильный метод - использовать setFetchSize.

По умолчанию, когда Oracle JDBC выполняет запрос, он получает набор результатов. 10 строк за раз от курсора базы данных. Это по умолчанию Значение размера выборки строки Oracle. Вы можете изменить количество строк извлекается при каждой поездке в базу данных курсором путем изменения строки значение размера выборки.

Стандартный JDBC также позволяет указывать количество выбранных строк с каждым обращением к базе данных для запроса, и этот номер называется в качестве размера выборки. В Oracle JDBC используется значение предварительной выборки строк в качестве размера выборки по умолчанию в объекте оператора. Установка выборки размер переопределяет настройку предварительной выборки строк и влияет на последующие запросы выполнить этот объект оператора.

Размер выборки также используется в наборе результатов. Когда объект оператора выполняется запрос, размер выборки объекта оператора передается объект набора результатов, созданный запросом. Тем не менее, вы также можете установить размер выборки в объекте набора результатов для переопределения оператора выборки размер, который был передан ему.

1 голос
/ 05 июня 2014

daveslab, немного больше информации ...

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

Настройка размера предварительной выборки может повлиять на производительность приложения.Увеличение размера предварительной выборки уменьшит количество циклов, необходимых для получения всех данных, но увеличит использование памяти.Это будет зависеть от количества и размера столбцов в запросе и количества ожидаемых строк.Также это будет зависеть от памяти и загрузки процессора клиентского компьютера JDBC.Оптимальным является то, что автономное клиентское приложение будет отличаться от сильно загруженного сервера приложений.Также следует учитывать скорость и задержку сетевого подключения.

Клиент Oracle JDBC, кажется, предварительно инициализирует некоторые структуры памяти для хранения полного размера предварительной выборки.Таким образом, если вы установите размер предварительной выборки 500, в 50 раз вы выделите больше памяти, чем если бы у вас был размер предварительной выборки = 10. Это огромная дополнительная нагрузка на GC, особенно если вы на самом деле не читаете эти строки.Можно подумать, что вы можете запустить GC в 50 раз чаще, чем нужно, если вы обычно выбираете только несколько строк;это сильно повлияет на скорость отклика вашего приложения.

Если возможно, я рекомендую использовать setFetchSize для каждого запроса.Например, если вы знаете, что конкретный запрос будет когда-либо возвращать только несколько строк, то установите размер выборки равным 5. Если вы знаете, что запрос вернет 1000 строк, используйте размер выборки 100.

Какэвристика, преимущества от 50 до 100 ограничены.

Надеюсь, вы понимаете, я использую переводчик Google.

1 голос
/ 14 февраля 2012

В значительной степени то, что сказал Адам Х. - не существует универсальных настроек для каждого типа сценариев. Oracle требует времени для извлечения строк, поэтому время, которое он потратил на ожидание строк на стороне сервера, прежде чем отправлять его клиенту, могло быть потрачено в вашем приложении, если порог предварительной выборки будет установлен ниже, что приведет к снижению производительности.

Насколько я помню, Oracle также использует кэширование на стороне клиента для предоставления прокручиваемых курсоров. Это может помочь установить курсор только вперед, по крайней мере, с точки зрения памяти. По крайней мере, это было полезно в старых версиях драйвера JDBC, возможно, поведение изменилось с тех пор.

Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...