LINUX.ORG.RU

Oracle DB крайне медленная передача данных по сети

 , ,


2

2

Столкнулся с очень странной проблемой, раньше такого не встречал.

Дано:

Java-приложение запущенное локально, Oracle DB на удаленном сервере. Скорость соединения между ними - 2.5MB/s.

В приложении выполняем очень простой запрос вида «select id, name from table_name», запрос возвращает ~60K строк, общий размер данных - 1,5 Мб, время выполнения - 80 сек. Профайлер говорит, что всё это время приложение висит в методе oracle.net.Packet.receive.

Ок, открываем SQL Developer, выполняем тот же самый запрос - 0,6 сек/5000 строк, т.е. примерно 7-8 секунд на всю выборку. Повторяем то же самое в DBeaver - 7 сек/5000 строк или 80 сек, если убрать ограничение на размер выборки.

Какая-то нездоровая фигня получается. Берем в руки tcpdump и смотрим, как передаются данные от базы к нам. В случае Java-приложения и DBeaver данные передаются в пакетах размером ~200 байт, SQLDeveloper получает данные в пакетах ~2000 байт.

Ладно, лезем в официальную доку https://docs.oracle.com/cd/E18283_01/network.112/e10836/performance.htm#i1006332, находим что нам надо поднять размер SDU/TDU. На стороне базы я не могу ничего менять, таково требование заказчика. Пробуем добавить эти параметры на стороне клиента, получается вот такой URL:

jdbc:oracle:thin:@(DESCRIPTION=(SDU=11280)(TDU=11280)(ADDRESS=(PROTOCOL=tcp)(HOST=<host>)(PORT=1521)(SEND_BUF_SIZE=11784)(RECV_BUF_SIZE=11784))(CONNECT_DATA=(SERVICE_NAME=<db>)))
И ничего не происходит, время то же, размер пакетов такой же. WTF? База игнорит передаваемые ей параметры или драйвер ей просто их не передает? Или может я вообще не то пытаюсь поправить и истина где-то в другой бочке вина?

★★★★★

Вроде dbeaver использует тот же самый jdbc driver, да и sql developer скорее всего тоже. Не должно быть особой разницы - смотрите параметры соединения.

BattleCoder ★★★★★
()
Ответ на: комментарий от BattleCoder

У oracle хитрый драйвер, потому как sqldeveloper например поддерживает ленивую загрузку в отображаемые таблицы, которая, если ничего не путаю, держит курсор на результаты выборки, а это фишка не из стандарта jdbc.

Aber ★★★★★
()

Да, дело в fetch size скорее всего.

orm-i-auga ★★★★★
()
Ответ на: комментарий от Aber

И правда помогло, по-умолчанию там вообще defaultRowPrefetch = 10. Поставил 1000, с 80 сек. упало до 0,7 сек.

В общем, спасибо всем, проблема решена, похоже.

hippi90 ★★★★★
() автор топика
Ответ на: комментарий от hippi90

defaultRowPrefetch = 10. Поставил 1000, с 80 сек. упало до 0,7 сек.

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

Statement stmt = conn.createStatement(); 
...
((OracleStatement)stmt).setRowPrefetch(1000); 

vtVitus ★★★★★
()
Ответ на: комментарий от vtVitus

Да, спасибо за совет, я прекрасно понимаю, чем это чревато, но по крайней мере, я знаю что крутить. Подобрать конкретное значение параметра это сильно проще. В любом случае регрессионные тесты надо делать.

hippi90 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.