2011-12-07 7 views
0

Hibernateクエリがデータをどこから取得しているか(セゾン・キャッシュかセカンド・レベル・キャッシュか、またはdbか)を判断する信頼性の高い方法はありますか?私は次のプロパティをHibernateに設定した場合:Hibernate Profiling

<prop key="hibernate.show_sql">true</prop> 
<prop key="hibernate.format_sql">true</prop> 

(彼らはから取得される場合、私は知りませんが)私が実行されている選択についての情報のトンを受け取ります。これは、Spring MVCのアプリケーションである、と私たちのすべての要求は、私は以下の迎撃を作成した春のコントローラで処理されているので:

private static final class HibernateStatistics implements Serializable { 
    private static final long serialVersionUID = 1L; 
    private long queryExecutions = 0; 
    private long transactions = 0; 
    private long entityLoads = 0; 
    private long connects = 0; 
    private long time = 0; 
    private double secondLevelHits = 0; 
    private double secondLevelMisses = 0; 
    private double queryHits = 0; 
    private double queryMisses = 0; 

    public HibernateStatistics(Statistics stats) { 
    synchronized(stats) { 
     queryExecutions = -stats.getQueryExecutionCount(); 
     transactions = -stats.getTransactionCount(); 
     entityLoads = -stats.getEntityLoadCount(); 
     connects = -stats.getConnectCount(); 
     secondLevelHits = -stats.getSecondLevelCacheHitCount(); 
     secondLevelMisses = -stats.getSecondLevelCacheMissCount(); 
     queryHits = -stats.getQueryCacheHitCount(); 
     queryMisses = -stats.getQueryCacheMissCount(); 
     time = -System.currentTimeMillis(); 
    } 
    } 

    public void update(Statistics stats) { 
    synchronized(stats) { 
     queryExecutions += stats.getQueryExecutionCount(); 
     transactions += stats.getTransactionCount(); 
     entityLoads += stats.getEntityLoadCount(); 
     connects += stats.getConnectCount(); 
     secondLevelHits += stats.getSecondLevelCacheHitCount(); 
     secondLevelMisses += stats.getSecondLevelCacheMissCount(); 
     queryHits += stats.getQueryCacheHitCount(); 
     queryMisses += stats.getQueryCacheMissCount(); 
     time += System.currentTimeMillis(); 
    } 
    } 

    @Override 
    public String toString() { 
    return "Stats" 
    + "[ queries=" + queryExecutions 
    + ", xactions=" + transactions 
    + ", loads=" + entityLoads 
    + ", connects=" + connects 
    + ", queryCacheHits=" + queryHits 
    + ", secondLevelCacheHits=" + secondLevelHits 
    + ", time=" + time + " ]"; 
    } 
} 

ここ
public class ProfilingInterceptor implements HandlerInterceptor { 

    @Autowired private SessionFactory sessionFactory; 
    private static final String STATS = "hibernateStats"; 
    private static final String START_TIME = "startTime"; 
    private static final Logger LOGGER = Logger.getLogger(ProfilingInterceptor.class); 

    @Override public boolean preHandle(HttpServletRequest request, 
            HttpServletResponse response, 
            Object handler) throws Exception { 
    request.getSession().setAttribute(START_TIME, System.currentTimeMillis()); 
    request.getSession().setAttributes(STATS, new HibernateStatistics(sessionFactory.getStatistics()); 
    return true; 
    } 

    @Override public boolean postHandle(HttpServletRequest request, 
            HttpServletResponse response, 
            Object handler) throws Exception { 
    HibernateStatistics stats = (HibernateStatistics) 
           request.getSession().getAttribute("STATS"); 
    stats.update(sessionFactory.getStatistics()); 
    request.getSession().setAttribute(STATS, new HibernateStatistics(sessionFactory.getStatistics())); 
    LOGGER.debug(stats); 
    } 

    @Override public boolean postHandle(HttpServletRequest request, 
            HttpServletResponse response, 
            Object handler, 
            Exception ex) throws Exception { 
    long startTime = (Long) request.getSession().getAttribute(START_TIME); 
    long currentTime = System.currentTimeMillis(); 
    request.getSession().setAttribute(START_TIME, null); 
    long totalTime = currentTime - startTime; 
    LOGGER.debug("URI: " request.getRequestURI() + " Method: " 
       + request.getMethod() + " took " + totalTime + "ms."); 
    HibernateStatistics stats = (HibernateStatistics) 
           request.getSession().getAttribute(STATS); 
    stats.update(sessionFactory.getStatistics()); 
    LOGGER.debug(stats); 
    } 
} 

はHibernateStatisticsオブジェクトが(それは内部クラスです)のように見えるものです

私はコード内でN + 1のクエリの問題が発生する状況を見つけるためにシングルスレッドテストを利用していますが、この時点では私たちの接続数とトランザクション数はすべてのページでよく見えます。

私が今必要とするのは、2番目のレベルとクエリのキャッシュがどれほど効果的かを判断する良い方法です。問題は、HibernateStatisticsがスレッドセーフではないという点にあります。ですから、私たちがマルチスレッドにしようとすると、私はこれらの値にいくつかの奇妙な数字を見ることができました。統計情報を収集し、さらに解析するためにページに表示するのは簡単ですか?

答えて

2

なぜリクエストを中心に統計情報を渡すのですか? SessionFactoryをシングルトンとしてコンフィグレーションしたと仮定すると、sessionFactory.getStatistics()はアプリケーション内で呼び出した回数と回数を常に返します。統計を記録するために、HibernateStatisticsクラスを使用する必要はありません。統計情報を記録できるstatic utilメソッドを実装することができます。セッションファクトリは、統計が初期化された瞬間から統計を累積します。

私はデータベースからロードされていることを意味する選択肢がログにあります。セッション/第2レベルのキャッシュからのものである場合、クエリはハイバネートによってログに記録されません。キャッシュのパフォーマンスをチェックする唯一の信頼できる方法は、キャッシュの統計情報のヒット/ミス率を監視することです。エンティティレベルで統計を有効にすることもできます。チェックhere.

+0

私はそれを渡している理由は、私は簡単に数字の変更を見ることができますです。私は確かに要求の各段階で数字を印刷することができましたが、手動で数学を行う必要があります。セッション中にそれらを保持する(事前に否定された)ことにより、Javaで、そしてその後UIで、いくつのトランザクション、接続などが実行されたかを素早く確認することができます。ログ内の選択項目について私が見逃したドキュメントがありますか?クエリの一部がキャッシュされていることはわかっていますが、依然として印刷されています。 – Scott

関連する問題