2015-06-11 9 views
4

По необъяснимым причинам, однако, сегодня утром производительность увеличилась для двух моих запросов, которые были медленными. Понятия не имею почему.
У меня нет полномочий над сервером, возможно, кто-то что-то изменил.
Проблема не более.Время выполнения SQL намного медленнее в сервлете Tomcat, чем в обычной программе Java

В двух словах:

  • s.executeQuery (SQL) работает очень медленно в TOMCAT сервлет на сервере
  • же запрос работает нормально без сервлет (простой Java программы) на той же машине
  • Не все запросы медленны в сервлете. Лишь немногие из них делают большие
  • же сервлет работает быстро на другой машине

UPDATES

Пожалуйста, прочитайте обновления ниже текст!

У меня есть servlet, который выполняет запросы SQL и отправляет результаты через JSON. По некоторым причинам для выполнения некоторых запросов требуется огромное количество времени, но когда я запускаю их в любом Oracle SQL Client, они выполняются в кратчайшие сроки.

Я говорю о разнице в 1 секунду против 5 минут для того же SQL (что не так сложно).

Как это можно объяснить? Есть ли способ повысить производительность Java-запроса на основе Java?

Я использую традиционный способ выполнения запросов:

java.sql.Connection conn = null; 
java.sql.Statement s = null; 
ResultSet rs = null; 

String dbDriver = "oracle.jdbc.driver.OracleDriver"; 
String dbConnectionString = "jdbc:oracle:thin:@" + dbHost + ":" + dbPort + ":" + dbSid; 

Class.forName(dbDriver).newInstance(); 
conn = DriverManager.getConnection(dbConnectionString, dbUser, dbPass); 
s = conn.createStatement(); 
s.setQueryTimeout(9999); 
rs = s.executeQuery(newStatement); 
ResultSetMetaData rsmd = rs.getMetaData(); 

// Get the results 
while (rs.next()) { 
// collect the results 
} 

// close connections 

Я попытался с ojdbc14 и ojdbc6, но не было никакой разницы.

UPDATE 1: Я попробовал один и тот же SQL в локальном проекте Java (не сервлета) на клиентской машине, и я получаю результаты немедленно. Итак, я предполагаю, что проблема возникает из моего сервлета или конфигурации tomcat?

ОБНОВЛЕНИЕ 2: Виновником действительно Rs = s.executeQuery (MySql); Вместо этого я попытался использовать prepareStatement, но нет никакой разницы.

UPDATE 3: Я создал новый сервлет, работающий на локальном Tomcat, и запрос быстро возвращается. Поэтому проблема возникает из моего производственного сервера или конфигурации Tomcat. Любые идеи о том, какие элементы конфигурации могут повлиять на это?

UPDATE 4: Я попробовал тот же самый код в обычной Java программы вместо сервлета (до сих пор на том же сервере), и результаты приходят быстро. Ergo проблема исходит от самого сервлета (или Tomcat?).До сих пор не знаю, что делать, но я сузили его :)

UPDATE 5: Jstack показывает следующее (Она начинается там, где мой сервлет, я вырезал остальное)

"http-8080-3" daemon prio=3 tid=0x00eabc00 nid=0x2e runnable [0xaa9ee000] 
    java.lang.Thread.State: RUNNABLE 
     at java.net.SocketInputStream.socketRead0(Native Method) 
     at java.net.SocketInputStream.read(SocketInputStream.java:129) 
     at oracle.net.ns.Packet.receive(Packet.java:311) 
     at oracle.net.ns.DataPacket.receive(DataPacket.java:105) 
     at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:305) 
     at oracle.net.ns.NetInputStream.read(NetInputStream.java:249) 
     at oracle.net.ns.NetInputStream.read(NetInputStream.java:171) 
     at oracle.net.ns.NetInputStream.read(NetInputStream.java:89) 
     at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:123) 
     at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:79) 
     at oracle.jdbc.driver.T4CMAREngineStream.unmarshalUB1(T4CMAREngineStream.java:429) 
     at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:397) 
     at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257) 
     at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587) 
     at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:210) 
     at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:30) 
     at oracle.jdbc.driver.T4CStatement.executeForDescribe(T4CStatement.java:762) 
     at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:925) 
     at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1104) 
     at oracle.jdbc.driver.OracleStatement.executeQuery(OracleStatement.java:1309) 
     - locked <0xe7198808> (a oracle.jdbc.driver.T4CConnection) 
     at oracle.jdbc.driver.OracleStatementWrapper.executeQuery(OracleStatementWrapper.java:422) 

Итак, я застрял в java.net.SocketInputStream.socketRead0(Native Method)?

+0

Является ли клиент на той же машине, что и клиент «jdbc»? Как насчет дозирования? – Jayan

+1

Вы сравниваете на одной основе? Ваш код печатает набор результатов, вы делаете то же самое с SQL-клиентом? Обычно запрос выполняется очень быстро, но передача данных и их отображение также занимает много времени. И кстати: вы должны использовать пул соединений. Вы проверили, возможно ли время, проведенное во время входа? Еще один совет: вы можете использовать dbVisualizer для подключения к базе данных. Он написан на одном языке (Java), но оптимизирован. Таким образом, вы можете увидеть, есть ли проблема в Java/драйвер или ваш код. – Marged

+0

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

ответ

1

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

1

В некоторых случаях (не уверен, что это применимо к вашей) установка fetchSize на объекте Statement дает большие улучшения в производительности. Это зависит от размера получаемого набора результатов.

Попробуйте сыграть с ним, установив его на нечто большее, чем значение по умолчанию 10 для Oracle (см. this link).

См. Statement.setFetchSize.

+0

Спасибо, но ничего не изменил – Tim

1

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

Так что вам, вероятно, нужно взглянуть на системные причины, по которым сервер SQL работает медленно и как это можно привязать к Tomcat. Мой опыт в таких случаях - это, как правило, диск, поэтому я был бы склонен проверять, является ли ваш пейджинг из-за нехватки оперативной памяти при загрузке Tomcat или страдает от гораздо более высоких операций с дисками из-за уменьшения дискового кэша. Предполагая, что вы работаете в UNIX-варианте, я бы посмотрел vmstat и iostat на рабочий и сломанный случай, чтобы устранить такие проблемы.

+0

Я уже проверил эти параметры, и я даже изменил параметры jvm для Tomcat. Однако по необъяснимым причинам, сегодня утром производительность увеличилась, и моей проблемы больше нет. Понятия не имею почему. У меня нет полномочий над сервером, может, кто-то что-то изменил. – Tim

+0

О, хорошо. По крайней мере, сейчас это работает. Кстати, я предположил, что ваш БД и веб-сервер находятся на одной машине. Если нет, вы можете просто обнаружить, что БД недостаточно работает с большими запросами для любых связанных с этим ограничений ресурсов. –

0

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

производительности базы данных Проверьте, чтобы убедиться, не экземпляр, ни запрос получать влияние на какой-то момент время в течение дня?

Проверьте свои сетевые задержки между серверами Java и DB. То же, что и выше. Возможно, traceroute?

+0

Производительность БД не является проблемой - такой же запрос выполняется быстро за пределами сервлета на том же компьютере – Tim

+0

Что относительно сетевых латентных событий между приложениями и сервером БД? – bubooal

+0

Я исключил это, так как большинство SQL-запросов быстро запускаются в сервлет. И теперь новые тоже. – Tim

0

Поскольку вы не поставили query, я могу дать вам сценарий, где это возможно. Если вы используете функцию в своем запросе типа to_char и т. Д., Тогда ваши индексы таблицы не будут использоваться при выполнении запроса через JDBC, но будут работать нормально, если вы запустите его в консоли. Я не знаю, почему, но есть что-то с драйвером JDBC. У меня была такая же проблема в db2, и я решил удалить функции.

Другой сценарий может заключаться в том, что огромное количество записей не загружается, а правильная дозировка не выполняется.