2012-02-26 5 views
18

私はプロファイラの下でアプリケーションをテストし、SQL文字列が私のメモリの約30%を使用していることを知りました!これは奇妙です。Hibernateはすべてのクエリに対して異なるSQLを生成します

このような文字列がアプリメモリに格納されています。これは、Hibernateによって生成されたSQLクエリで、異なる番号をメモして末尾のアンダースコア:ここ

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

は、私が理解できない部分です。なぜハイバーネーションは、クエリごとに "Id4305_0_"のような異なる識別子を持つ異なるSQL文字列を生成する必要がありますか?すべての同じクエリに1つのクエリ文字列を使用できないのはなぜですか?これはクエリキャッシングをバイパスするための何らかのトリックですか?

誰かが私になぜそれが起こっているのか、そのようなリソースの浪費を避ける方法を説明すると大変感謝します。

UPDATE

[OK]をクリックします。見つけた。私はメモリリークを仮定して間違っていた、それは私のせいだった。 Hibernateは意図したとおりに動作しています。

私のアプリは、10スレッドで121(!)のSessionFactoriesを作成し、SingleTableEntityPersistersのインスタンスを約2300作成しました。また、各SingleTableEntityPersisterは、異なる識別子を持つ約15のSQLクエリを生成します。 Hibernateは約345,000の異なるSQLクエリを生成するように強制されました。すべてがうまくいっていて、奇妙なものではありません:)

+1

あなたは単純なマッピングの設定、テストコードとこのような状況を再現する単純なテーブルのDDLを提供することができればそれが役に立つかもしれません。私の経験では、Hibernateがそのような高いカラム別名インデックスカウントを作成することは決して見たことがありません。 –

+0

良い点。私は明日お試しになります。 :) –

+0

@AndrewFrolov:私の答えがあなたのupdates.In場合は、問題を見つけて訂正して、あなたのupdates.Inとの質問に今フィットすることを願って! – ManuPK

答えて

1

ハイバネートが生成するクエリ文字列の背後にロジックがあります。その主な目的は、がテーブルとカラムの名前にユニークな別名を取得することです。あなたのクエリから

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

avatardata0_ ==>avatardataは、テーブルの別名であると0_は、クエリ内の最初の表であることを示すために追加されます。したがって、クエリの2番目のテーブル(またはエンティティ)の場合は、avatardata1_と表示されていたはずです。これは、列の別名に同じロジックを使用します。

このように、考えられるすべての競合は回避されます。

設定をshow_sqlに設定しているため、これらのクエリが表示されます。 これは、クエリのデバッグを目的としています。アプリケーションが動作するようになったら、それを無効にすることになっています。

続きを読むAPIドキュメントhere

メモリ消費量はあまり気にしませんが、上記のフラグをオフにしてテストを繰り返し、改善があるかどうかを確認します。

+1

show_sqlはオフです。私はログについては話していません、私は記憶について話しています。私はプロファイラでこのクエリを参照してください、おそらく内部のハイバネートキャッシュにアプリのメモリで。私は結果セット内の各列のエイリアスを作成する理由を理解しています。なぜ私はハイバネートが次のクエリのために生成されたステートメントを再利用することができないのか理解していない。 –

+0

それを得ました。私は**なぜ名前が長く**部分について答えましたか?私は解決策についてもわからない! – ManuPK

+0

あなたは*なぜ彼らがこれを説明しているかについての説明書はありますか?それは時々パフォーマンスの問題を引き起こす可能性があります... http://stackoverflow.com/a/15257317/32453 – rogerdpack

1

sqlサーバを使用していると仮定すると、 '?'のパラメータ型宣言をチェックして、毎回同じ固定長宣言が宣言されるようにすることができます。

動的長さパラメータは、クエリごとに別々の実行計画になります。これはおそらく多くのリソースを消費する可能性があります。同じプロシージャとして見ると、getはSQL Serverによって別のクエリとして解釈され、別の実行計画がレンダリングされます。

したがって、

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

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

は異なる計画をもたらすであろう。単純に@ p1の宣言はサイズが異なります。

この動作について知るべきことはたくさんあります。上記があなたに当てはまる場合は、「パラメータスニッフィング」をお読みになることをお勧めします。

-1

いいえ...ハイバネート内で一般的なクエリを生成できます。その背後にある論理は、テーブルとマッピングしてそこからレコードをフェッチすることです。これは、すべてのデータベースに対して一般的なクエリとして使用されます。そのような一般的なクエリを作成してください:

例:

select t.Id as Id4305_0_,...... from t where t.Id=? 
関連する問題