Проблемы с производительностью JDBC - PullRequest
9 голосов
/ 02 ноября 2010

В настоящее время я сталкиваюсь с проблемой, когда конкретный SQL-запрос занимает около 30 секунд для выполнения из моего Java-приложения, но менее 1 секунды в SQL-клиенте (SQL Developer).

В вопросе
Медленный запрос в Java от JDBC, но не в других системах (TOAD) , предполагается, что использование PreparedStatement, привязанного к переменным Java, может сделать запрос намного медленнее, чем в SQL-клиенте (в данном случае TOAD). ) потому что Oracle не понимает, какие индексы использовать. Может ли это быть проблемой с PreparedStatement без параметров?

В чем может быть проблема?

Запрос выглядит примерно так:

select 
sum(col1),
sum(col2),
max(select ...)
from view_
where time_id = get_time_id(to_date('2010-10-10','yyyy-mm-dd'))

где view_ - сложное представление, содержащее совокупности таблиц и других сложных представлений. Запрос выполняется как PreparedStatement, но без каких-либо параметров. Похоже, не имеет значения, используем ли мы подготовленное утверждение или просто простое.

Так как план выполнения довольно велик, я не могу опубликовать все, если он здесь, но похоже, что существенная разница:

UNION-ALL 
TABLE ACCESS FULL GVC_WH.PLAYER_FACT_DAILY TABLE 37 6717151 596,934.317 19940 240 7621178231 19502 
UNION-ALL 
TABLE ACCESS BY INDEX ROWID GVC_WH.PLAYER_FACT_DAILY TABLE 38 2657 236.120 2429 30 20544658 2428 
INDEX RANGE SCAN GVC_WH.PK_AGG_PLAYER INDEX (UNIQUE) 37 2657 16 1 638743 16 

Откуда берется первый фрагмент при запуске его с тонким клиентом JDBC, а второй - при запуске его в SQL Developer. Он не выбирает правильный индекс при запуске в качестве оператора (не имеет значения, использую ли я подготовленный оператор или нет) с Тонким клиентом JDBC. Разница во времени составляет 30 секунд для первого и 0,5 секунды для второго.

Может ли быть так, что использование функции get_time_id запрещает использование индекса при его использовании через JDBC, даже если он не является функцией столбца и даже если он работает в SQL Developer?

Ответы [ 3 ]

2 голосов
/ 04 октября 2011

Я бы попытался запустить trace в базе данных при использовании приложения.

Тогда вы сможете увидеть выполняемый запрос и фактический план выполнения.Это точно покажет вам, что происходит, то есть идет ли речь о индексах или нет.

1 голос
/ 02 ноября 2010

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

alter session set “_optim_peek_user_binds”=false;

Статистика актуальна для всех объектов?

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

0 голосов
/ 18 октября 2013

Убедитесь, что кто-то не установил свойство oracle.jdbc.defaultNChar = true

Иногда это делается для решения проблем с юникодом, но это означает, что все столбцы обрабатываются как nvarchars. Если у вас есть индекс для столбца varchar, он не будет использоваться, потому что oracle должен использовать функцию для преобразования кодировки символов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...