Hibernate создает разные SQL для каждого запроса - PullRequest
21 голосов
/ 26 февраля 2012

Я только что протестировал свое приложение под профилировщиком и обнаружил, что строки sql используют около 30% моей памяти! Это странно.

В памяти приложения хранится много подобных строк. Это SQL-запросы, сгенерированные Hibernate, обратите внимание на различные цифры и последние подчеркивания:

select avatardata0_.Id as Id4305_0_,...... where avatardata0_.Id=? for update
select avatardata0_.Id as Id4347_0_,...... where avatardata0_.Id=? for update

Вот часть, которую я не могу понять. Почему hibernate должен генерировать разные строки sql с разными идентификаторами, такими как " Id4305_0_ " для каждого запроса? Почему он не может использовать одну строку запроса для всех идентичных запросов? Это какой-то трюк, чтобы обойти кеширование запросов?

Буду очень признателен, если кто-нибудь опишет, почему это происходит и как избежать такой потери ресурсов.

UPDATE

Ok. Я нашел это. Я ошибался, предполагая утечку памяти, это была моя вина Hibernate работает как задумано.

Мое приложение создало 121 (!) SessionFactories в 10 потоках, они произвели около 2300 экземпляров SingleTableEntityPersisters. И каждый SingleTableEntityPersister генерирует около 15 SQL-запросов с разными идентификаторами. Hibernate был вынужден генерировать около 345 000 различных запросов SQL. Все хорошо, ничего странного:)

Ответы [ 3 ]

1 голос
/ 30 марта 2012

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

Параметры динамической длины приводят к отдельным планам выполнения для каждого запроса. Это может потребовать много ресурсов. То, что мы видим как одну и ту же процедуру, get интерпретирует sql server как другой запрос, представляя отдельный план выполнения.

Таким образом,

exec myprocedure @p1 varchar(3)='foo' 

и

exec myprocedure @p1 varchar(6)='foobar' 

приведет к другим планам. Просто тем, что объявления @ p1 отличаются по размеру.

Существует много информации об этом поведении. Если вышеизложенное относится к вам, я бы порекомендовал вам ознакомиться с «анализом параметров».

1 голос
/ 27 февраля 2012

За строкой запроса, которую генерирует hibernate, есть логика.Его основная цель - получить уникальные псевдонимы для имен таблиц и столбцов.

По вашему запросу

select avatardata0_.Id as Id4305_0_,...... where avatardata0_.Id=?

avatardata0_ ==> avatardata - это псевдоним таблицы, а 0_ добавляется, чтобы указать, что это первая таблица в запросе.Таким образом, если бы это была вторая таблица (или сущность) в запросе, она должна была бы отображаться как avatardata1_.Он использует ту же логику для псевдонимов столбцов.

Таким образом, все возможные конфликты исключаются.

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

Подробнее об API документации здесь .

Я не очень осведомлен о потреблении памятичасть, но вы повторяете свои тесты с отключенным флагом и смотрите, есть ли улучшения.

0 голосов
/ 10 сентября 2012

Нет ... вы можете создать свой общий запрос в спящем режиме.Логика заключается в сопоставлении с таблицей и получении записи оттуда.Используется общий запрос для всей базы данных.Пожалуйста, создайте общий запрос, подобный этому:

Пример:

select t.Id as Id4305_0_,...... from t where t.Id=?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...