Подтвердить что ты не робот

Медленная производительность на Hibernate + Java, но быстро, когда я использую TOAD с тем же собственным запросом Oracle

Я обнаружил проблему с производительностью с гибернацией и встроенными запросами в Oracle. Когда я выполняю сложный SQL-запрос с несколькими параметрами в TOAD, я получаю результат в miliseconds. Однако при выполнении одного и того же запроса с использованием Hibernate это время увеличивается с увеличением (до четырех секунд или даже больше).

Мой SQL-запрос довольно сложный, возвращает уникальное значение (поэтому проблема не связана с временем, необходимым для классов instation) и содержит несколько параметров с форматом: nameParameter. Этот запрос хранится в строке. Например,

String myNamedNativeQuery = "select count(*) from tables "+
                            "where column1 = :nameParameter1 "+ 
                            "and column2 = :nameParameter2";  
                            //actually my sentence is much more complex!!

Когда я выполняю предложение в TOAD, он разрешается за несколько миллисекунд. Но используя это предложение с Hibernate

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");

query.setParameter(nameParameter1, value1);
query.setParameter(nameParameter2, value2);

query.uniqueResult(); 

необходимы несколько секунд, чтобы получить тот же результат.

Я понял, что заменил параметры непосредственно на собственный запрос, а затем выполнил предложение, используя Hibernate, время резко сократилось. Это было бы так:

String strQuery = session.getNamedQuery("myNamedNativeQuery").getQueryString();

myNamedNativeQuery = myNamedNativeQuery.replace("nameParameter1", value1);
myNamedNativeQuery = myNamedNativeQuery.replace("nameParameter2", value2);

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");
query.uniqueResult(); 

Кто-нибудь знает, что происходит???

Спасибо заранее.

PS: версия Oracle - это 9i и Hibernate 3.2

4b9b3361

Ответ 1

Я думаю, что происходит с этим кодом:

SQLQuery query = session.createSQLQuery("myNamedNativeQuery");
query.setParameter(nameParameter1, value1);
query.setParameter(nameParameter2, value2);
query.uniqueResult(); 

:

в строке 1: план запросов создается на основе некоторых ожидаемых значений для ваших именованных параметров.

в строке 4: запрос выполняется со значением1 и значением2, но эти значения не являются "хорошими значениями" для плана запроса, который был разработан в строке 1, и поэтому база данных выполняет очень неулокальный план для фактических значений и это занимает много времени.

Почему?

Посмотрев исходный код HibernateSessionImpl.createSQLQuery(...), я нашел эту строку кода:

SQLQueryImpl query = new SQLQueryImpl(
                sql,
                        this,
                        factory.getQueryPlanCache().getSQLParameterMetadata( sql )
        );

который вызывает getQueryPlanCache() с некоторым параметромMetaData. Я предполагаю, что эти метаданные недостаточно хороши.

Ответ 2

Мой ответ вам:

Удалите все параметры привязки и используйте StatelessSession вместо сеанса

Использовать SQLQuery вместо запроса с полным SQL, включая значения параметров

StatelessSession session = sessionFactory.openStatelessSession();

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