Hibernateクエリ最適化HQL効率化


Hibernateクエリのパフォーマンスの最適化
1.Hibernate永続化フレームワークを用いてdao層のデータ操作を容易に解決するとともに、sqlの実行効率を高くし、発展させることも考慮すべき問題である.最近、チューニングの過程で、実は大部分の簡単なHQLはすべて最適化して簡略化することができて、プログラムが業務のロジックを処理することを達成すると同時に、プログラムの同時性能を大幅に向上することができます.
要点1:Hibernateのデフォルトでは、saveによるオブジェクト、同じsessionリクエストの範囲内など、ライフサイクルの終了までkey-valueとして存在する同じSessionライフサイクルの永続化オブジェクトをSession範囲の1レベルキャッシュでキャッシュします.Sessionライフサイクルについては、注釈クラスのアプリケーションでは、トランザクションが終了するまで、Sesseionがトランザクションに入った後に作成をブロックします.
要点2:Hibernateの怠惰なロード価値は、便利さをもたらすと同時に、多くの関連アプリケーションによる複雑なSQLクエリー2のパフォーマンス低下を防止することに注意しなければならない.たとえば、次のようなオブジェクトがあります.
機構:
public class Institution extends Unit implements Serializable {

	@Column(name = "[RELEASE]")
	@Version
	private Integer release = Integer.valueOf(0);
	/**
	 *     
	 */
	@Id
	@Column(name = "SID", length = 32)
	@GeneratedValue(generator = "system-uuid")
	@GenericGenerator(name = "system-uuid", strategy = "uuid.hex")
	private String id;
	/**
	 *     
	 */
	@Column(length = 60)
	private String code;
	/**
	 *     
	 */

	@Column(length = 150)
	private String name;
	/**
	 *   
	 */
	@Column(name = "[desc]")
	private String desc;

	@ManyToOne
	@Index(name = "INSTITUTION_P_IDX")
	private Institution parent;

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "parent")
	private Set children = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set users = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set roles = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set systemManagers = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set taskGroups = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set tasks = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set sheets = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set menus = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set institutionConnectionPools = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set institutionSimpleSQLModels = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set institutionTreeMenus = new HashSet();

	@OneToMany(cascade = CascadeType.ALL, mappedBy = "institution")
	private Set institutionRoleTypes = new HashSet();

ユーザ:略
ユーザー機構:InstitutionUser
@Entity
public class InstitutionUser implements Serializable {
	
	/**
	 *     
	 */
	@Id
	@Column(name = "SID", length = 32)
	@GeneratedValue(generator = "system-uuid")
	@GenericGenerator(name = "system-uuid", strategy = "uuid.hex")
	private String id;

	@ManyToOne
	@Index(name = "INSTITUTION_USER_IDX")
	private Institution institution;

	@ManyToOne
	@Index(name = "USER_INST_IDX")
	private User user;
	
	public InstitutionUser(){}
	
	public InstitutionUser(String institutionId){
		this.institution = new Institution();
		this.institution.setId(institutionId);
	}

ユーザによって機関などの情報を照会する場合、簡単には以下のようにする.
public List getInstitution(User user) {
		String queryString = "From InstitutionUser IU where IU.user.id='" + user.getId() + "'";
		List institutions = new ArrayList();
		List institutionUsers = this.query(queryString);
		for (InstitutionUser instUser : institutionUsers) {
			Institution institution = instUser.getInstitution();
			if (institution != null) {
				institutions.add(institution);
			}
		}
		return institutions;
	}

では、上記のメソッドを呼び出すときに印刷されるSQLは3つあり、クエリのデータ量は比較的大きいです.
Hibernate: select institutio0_.SID as SID79_, institutio0_.institution_SID as institut2_79_, institutio0_.user_SID as user3_79_ from JER_INSTITUTIONUSER institutio0_ where institutio0_.user_SID='402855b942099b1b0142099e148d0002'
Hibernate: select institutio0_.SID as SID69_1_, institutio0_.cls as cls69_1_, institutio0_.code as code69_1_, institutio0_.COMES as COMES69_1_, institutio0_.`desc` as desc5_69_1_, institutio0_.endData as endData69_1_, institutio0_.icon as icon69_1_, institutio0_.leaf as leaf69_1_, institutio0_.LEVEL_ as LEVEL9_69_1_, institutio0_.name as name69_1_, institutio0_.parent_SID as parent18_69_1_, institutio0_.path as path69_1_, institutio0_.`RELEASE` as RELEASE12_69_1_, institutio0_.startData as startData69_1_, institutio0_.text as text69_1_, institutio0_.upcode as upcode69_1_, institutio0_.url as url69_1_, institutio0_.useless as useless69_1_, institutio1_.SID as SID69_0_, institutio1_.cls as cls69_0_, institutio1_.code as code69_0_, institutio1_.COMES as COMES69_0_, institutio1_.`desc` as desc5_69_0_, institutio1_.endData as endData69_0_, institutio1_.icon as icon69_0_, institutio1_.leaf as leaf69_0_, institutio1_.LEVEL_ as LEVEL9_69_0_, institutio1_.name as name69_0_, institutio1_.parent_SID as parent18_69_0_, institutio1_.path as path69_0_, institutio1_.`RELEASE` as RELEASE12_69_0_, institutio1_.startData as startData69_0_, institutio1_.text as text69_0_, institutio1_.upcode as upcode69_0_, institutio1_.url as url69_0_, institutio1_.useless as useless69_0_ from JER_INSTITUTION institutio0_ left outer join JER_INSTITUTION institutio1_ on institutio0_.parent_SID=institutio1_.SID where institutio0_.SID=?
Hibernate: select user0_.SID as SID38_0_, user0_.accountRlace as accountR2_38_0_, user0_.birthDate as birthDate38_0_, user0_.bloodType as bloodType38_0_, user0_.code as code38_0_, user0_.COMES as COMES38_0_, user0_.comparePassword as compareP7_38_0_, user0_.computerCapacity as computer8_38_0_, user0_.dateReserve1 as dateRese9_38_0_, user0_.dateReserve2 as dateRes10_38_0_, user0_.demo as demo38_0_, user0_.desc_ as desc12_38_0_, user0_.eMail as eMail38_0_, user0_.education as education38_0_, user0_.endData as endData38_0_, user0_.entryDate as entryDate38_0_, user0_.foreignLanguageAbility as foreign17_38_0_, user0_.gender as gender38_0_, user0_.healthStatus as healthS19_38_0_, user0_.height as height38_0_, user0_.hobby as hobby38_0_, user0_.idType as idType38_0_, user0_.idValue as idValue38_0_, user0_.instituion as instituion38_0_, user0_.LEVEL_ as LEVEL25_38_0_, user0_.marriageType as marriag26_38_0_, user0_.mobilePhone as mobileP27_38_0_, user0_.name as name38_0_, user0_.nation as nation38_0_, user0_.nativePlace as nativeP30_38_0_, user0_.officePhone as officeP31_38_0_, user0_.password as password38_0_, user0_.passwordUpdata as passwor33_38_0_, user0_.politicsStatus as politic34_38_0_, user0_.position as position38_0_, user0_.post as post38_0_, user0_.speciality as speciality38_0_, user0_.startData as startData38_0_, user0_.state as state38_0_, user0_.strReserve1 as strReserve40_38_0_, user0_.strReserve2 as strReserve41_38_0_, user0_.strReserve3 as strReserve42_38_0_, user0_.strReserve4 as strReserve43_38_0_, user0_.strReserve5 as strReserve44_38_0_, user0_.useless as useless38_0_ from JER_TUSER user0_ where user0_.SID=?

しかし、実際には、彼のメカニズムに戻るか、実際のアプリケーションでは2次キャッシュに保存されます.ビジネス操作では、メカニズムのidしか使用できません.これにより、クエリーの効率が大幅に向上します.
String queryString = "select new InstitutionUser(IU.institution.id) From InstitutionUser IU where IU.user.id='" + user.getId() + "'";
Hibernate: select institutio0_.institution_SID as col_0_0_ from JER_INSTITUTIONUSER institutio0_ where institutio0_.user_SID='402855b942099b1b0142099e148d0002'

もちろん、上記は単純な例ですが、実際にどのような属性が必要なのかはプログラムによって決まり、エンティティがキャッシュを使用しているかどうかなどの要因も考慮されます.
大きなアプリケーションでは、各機能モジュールをできるだけ最適化すると、アプリケーション全体の同時パフォーマンスが大幅に向上します.