Любое решение для неэффективности Oracle TNS (много циклических переходов, задержка) из приложения Java? - PullRequest
6 голосов
/ 09 октября 2010

Я смотрел на очень медленный SQL-запрос (происходящий из приложения Java с использованием Hibernate, развернутого в JBoss 5.1).Этот конкретный запрос возвратил около 10 тыс. Записей, но все равно занял 40 с или более.

В итоге я перехватил трафик с базой данных (у wireshark есть диссектор для TNS) и обнаружил нечто неожиданное.Когда данные поступали с сервера, каждая строка результатов была в своем собственном пакете TNS.Кроме того, каждый пакет TNS был подтвержден клиентом (т. Е. Сервером приложений) перед отправкой следующего из базы данных.Для 10K записей есть 10K туда-обратно, чтобы получить пакет и подтвердить его.Влияние на производительность огромно.

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

Если я выполняю тот же запрос от Oracle SQL Developer, я не вижу этот шаблон.Запрос выполняется примерно за 1/10 времени, без тысяч поездок туда и обратно.

Короткая версия : кажется, что проводной протокол Oracle (TNS) передает данные в одном пакете TNS на строку результатов запроса и требует, чтобы каждый пакет был подтвержден клиентом, прежде чем сервер отправит следующий..

Я нашел некоторую информацию об этом [здесь] [1] (прокрутите вниз до раздела «Параметры SDU и TDU в файле tnsnames.ora»).

И, таким образом, мой вопрос: возможно ли управлять поведением драйвера Oracle (я использую 10.2.0.4.0), чтобы протокол TNS был более эффективным?Опять же, это довольно стандартное приложение J2EE, развернутое в JBoss.

Большое спасибо!

Ответы [ 2 ]

6 голосов
/ 09 октября 2010

Настройте параметры SDU и TDU в tnsnames.ora и listener.ora

Чтобы установить размер пакета равным 100 для текущего состояния.

  ((OracleStatement)stmt).setRowPrefetch (100);

Примечание:

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

(из Руководство и справочник разработчика JDBC для Oracle Database )

Доступные свойства соединения здесь .

Также взгляните на Oracle UCP тоже.

3 голосов
/ 09 октября 2010

Попробуйте увеличить размер выборки для вашего объекта satement.

Я думаю, что по умолчанию 10, поэтому вы можете попробовать начать с 100.

Statement stmt = connection.createStatement();
stmt.setFetchSize(100);
ResultSet rs = stmt.executeQuery("SELECT ...");
...