Любое решение для неэффективности 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 ...");