Спящий режим - Избегание ненужного объединения при использовании внешнего ключа в предложении where
-
18-09-2019 - |
Вопрос
Я пытаюсь оптимизировать запросы к базе данных в режиме Гибернации, но я нашел блокировщик:
<class name="SupportedLanguageVO" table="AR_SUPPORTED_LANG" >
<cache usage="read-only"/>
<id name="Id" type="java.math.BigInteger">
<column name="ID" sql-type="NUMBER(20)" not-null="true"/>
<generator class="assigned"/>
</id>
<property name="OrderSeq" type="java.math.BigInteger">
<column name="ORDER_SEQ" sql-type="NUMBER(20)" not-null="true"/>
</property>
<many-to-one name="Country" class="CountryVO" column="CTRY_CD_ID" cascade="none" >
<many-to-one name="Language" class="LanguageVO" column="LANG_CD" cascade="none" >
</class>
Первичным ключом страны является CTRY_CD_ID
.Если я выполню следующие критерии
Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class);
crit.createCriteria("Country").add(Restrictions.eq("_CountryCode", p_countrycode));
crit.addOrder(Order.asc("OrderSeq"));
Я вижу, что hibernate объединяет таблицы ctry и AR_SUPPORTED_LANG.Почему?Было бы лучше убежать
select * from AR_SUPPORTED_LANG where ctry_cd_id=?
sql , а не
select * from AR_SUPPORTED_LANG inner join ctry .... where ctry_cd_id=?
Могу ли я принудительно перевести hibernate в режим гибернации для выполнения первого запроса?
Решение
Почему?Было бы лучше убежать...
Это не обязательно так, и на самом деле это сильно зависит от того, как ваша база данных оптимизирует свои запросы.Вообще говоря, внутреннее объединение будет более эффективным, поскольку у него есть возможность значительно сократить область поиска.Конечно, с простой таблицей типов, содержащей всего пару десятков строк, это выглядит излишеством.Добавьте пару миллионов строк, и вы увидите разницу.
По аналогичной причине обычно оптимально добавлять любые возможные подсказки к запросам в joins.Например (переписывание вашего запроса в HQL):
from AR_SUPPORTED_LANG inner join ctry c where c.cd_id=?
... должно быть...
from AR_SUPPORTED_LANG inner join ctry c WITH c.cd_id=?
Предложение WITH - это специфичный для HQL метод добавления предложений AND к операторам JOIN.
Другие советы
Попробуйте явно настроить режим выборки для ваших критериев:
crit.setFetchMode("Country", FetchMode.SELECT);
Я думаю, вы можете расставить на этом точки.Вы должны применить эквалайзер непосредственно к объекту country :
Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class);
crit.add(Restrictions.eq("Country", p_country));
crit.addOrder(Order.asc("OrderSeq"));
Таким образом, если я хорошо помню, hibernate должен оптимизировать запрос так, как вы хотите.Но это означает, что вам нужен объект country, а не только код страны.