Ruhezustand – Vermeidung unnötiger Verknüpfungen bei Verwendung eines Fremdschlüssels in der Where-Klausel
-
18-09-2019 - |
Frage
Ich versuche, die Datenbankabfragen im Ruhezustand zu optimieren, habe aber einen Blocker gefunden:
<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>
Der Primärschlüssel des Landes ist der CTRY_CD_ID
.Wenn ich die folgenden Kriterien ausführe
Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class);
crit.createCriteria("Country").add(Restrictions.eq("_CountryCode", p_countrycode));
crit.addOrder(Order.asc("OrderSeq"));
Ich kann sehen, dass der Ruhezustand die Tabellen ctry und AR_SUPPORTED_LANG verbindet.Warum?Es wäre besser zu rennen
select * from AR_SUPPORTED_LANG where ctry_cd_id=?
SQL statt
select * from AR_SUPPORTED_LANG inner join ctry .... where ctry_cd_id=?
Kann ich den Ruhezustand erzwingen, die erste Abfrage auszuführen?
Lösung
Warum?Es wäre besser zu laufen...
Das stimmt nicht unbedingt und hängt tatsächlich stark davon ab, wie Ihre Datenbank ihre Abfragen optimiert.Im Allgemeinen ist Inner Joining effizienter, da es die Möglichkeit bietet, den Suchumfang erheblich zu reduzieren.Bei einer einfachen Typtabelle mit nur ein paar Dutzend Zeilen sieht das natürlich wie ein Overkill aus.Fügen Sie ein paar Millionen Zeilen hinzu und Sie werden den Unterschied sehen.
Aus einem ähnlichen Grund ist es im Allgemeinen optimal, allen möglichen Abfragehinweisen zu Verknüpfungen hinzuzufügen.Zum Beispiel (Umschreiben Ihrer Abfrage in HQL):
from AR_SUPPORTED_LANG inner join ctry c where c.cd_id=?
...sollte sein...
from AR_SUPPORTED_LANG inner join ctry c WITH c.cd_id=?
Die WITH-Klausel ist eine HQL-spezifische Methode zum Hinzufügen von AND-Klauseln zu JOIN-Anweisungen.
Andere Tipps
Versuchen Sie explizit der Modus für Ihre Kriterien holen Einstellung:
crit.setFetchMode("Country", FetchMode.SELECT);
Ich glaube, Sie können es dot. Sie sollten die eq direkt auf dem Land Objekt anwenden:
Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class);
crit.add(Restrictions.eq("Country", p_country));
crit.addOrder(Order.asc("OrderSeq"));
So, wenn ich mich gut erinnere, überwintern sollte die Abfrage, wie Sie wollen optimieren. Aber das bedeutet, dass Sie das Land Objekt benötigen, nicht nur den Ländercode.