Подтвердить что ты не робот

Настройка размера выборки строк в Oracle делает приложение медленнее?

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

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

Спасибо!

EDIT:

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

ИЗМЕНИТЬ 2:

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

Размер выборки также используется в результирующем наборе. Когда объект утверждения запускается запрос, размер выборки объекта-оператора передается в объект набора результатов, созданный запросом. Однако вы также можете установить fetch size в объекте набора результатов, чтобы переопределить выбор изложения который был передан ему.

Ответ 4

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

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

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

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

Ответ 5

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

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

Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY);

Ответ 6

daveslab, дополнительная информация...

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

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

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

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

Как эвристика, есть ограниченные выгоды от перехода более 50-100.

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