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

Я смотрел на очень медленный 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 ответа

Решение

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

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

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

Замечания:

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

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

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

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

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

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

Оператор stmt = connection.createStatement();
stmt.setFetchSize(100);
ResultSet rs = stmt.executeQuery("SELECT ...");
Другие вопросы по тегам