2011-07-01 7 views
4

私のアプリケーションでは接続プーリングの形式が使用されていません。接続で直接作業しています。アプリケーションは、主に簡潔で簡単なクエリを実行します。ログから、頻繁に接続を開いたり閉じたりすることがわかります。しばしば、間に1つまたは複数の行を1つだけ選択します。これらは通常約100msかかる(接続の開閉を含む)。JDBCを使用した接続プーリングは、今日もパフォーマンスが向上していますか?

接続プーリングがアプリケーションのパフォーマンスを向上させる方法については数多くの記事とブログエントリがありますが、それらはすべてかなり古い(5年以上)ようです。

接続プールは、依然として妥当なパフォーマンス上の利点を提供するか、それとも時代遅れになっていますか。 SQLServer 2008とMicrosoftのJDBCドライババージョン3.0を使用しています。


結果/更新:私はこの質問をしてから多くのことが起こりました(私たちはJDBCドライバと他の多くのものを切り替えます)。ある時点で私は多くのリファクタリングやその他の作業を行い、そのアプリケーションで接続プールを追加しました。 接続では、いくつかのクエリをプールすることで、ログのタイムスタンプ粒度が測定できるよりも速く実行できるようになりました(私は信じている16ミリ秒以下)。

結論として、頻繁に接続/切断する必要がある場合は、接続プールは有効です。

答えて

4

クエリあたり100ミリ秒であれば、接続プールは不要です。 20ミリ秒未満のクエリが必要な場合は、接続を再利用することが不可欠です。

ドライバが独自の接続プールをサポートしている場合は、これを使用することをお勧めします。接続のプール方法をより詳細に制御したい場合にのみ、追加のライブラリを使用することができます(自分ではうまく使用できませんでした)

注:プールを使用して接続を再利用する必要はありません。

接続を再利用する簡単な方法の1つは、1つの永続的な接続(適切なスレッドセーフガードが適所にある)です。クエリがまれである場合は、これだけでよい場合もあります。

クエリを同時に実行でき、クエリを実行するスレッドがわずかしかない場合は、ThreadLocalフィールドに接続を保存できます。

複数の接続が必要で、接続に必要なスレッドよりも多くのスレッドが必要な場合は、プールを使用します。あなたが接続がクリーンアップされる方法を制御したい場合は、

public static final ThreadLocal<Connection> CONNECTION = new ThreadLocal<Connection>() { 
    public Connection initialValue() { 
     LOG.info(Thread.currentThread()+": created a connection."); 
     return createConnection(); 
    } 
}; 

を行うことができますThreadLocalのモデルについては

private static final Map<Thread, Connection> connections = new ConcurrentHashMap(); 
public static final ThreadLocal<Connection> CONNECTION = new ThreadLocal<Connection>() { 
    public Connection initialValue() { 
     LOG.info(Thread.currentThread()+": created a connection."); 
     Connection conn = createConnection(); 
     connections.put(Thread.currentThread(), conn); 
     return conn; 
    } 
}; 
public static void cleanUp() { 
    for(Map.Entry<Thread, Connection> entry: connections.entrySet()) { 
     Thread t = entry.getKey(); 
     if (!t.isAlive()) { 
      LOG.info(t+": closed a connection."); 
      connections.remove(t); 
      entry.getValue().close(); 
     } 
    } 
} 

デッド接続が発生することが懸念される場合は、ThreadLocalのget()をオーバーライドして接続をテストしてから返すことができます。

+0

1つの永続的なConnectionは機能しませんが、クエリを実行するスレッドの数は限られています(現在、2xCPUSに設定されていると思います)。私の場合、ThreadLocalのアイデアは実装するのがかなり簡単かもしれませんが、シャットダウン時に適切に閉じることは難しいでしょう。現時点では、接続時間に関する緊急のパフォーマンス問題はありませんが、クライアントがより広く使用されている場合は、これが変更される可能性があります。 – Durandal

+0

どのくらいの頻度でスレッドをシャットダウンしますか?あなたはこの静的なスレッドの数を保つことができますか?そうでなければ、 'Map 'のコレクションを持つことができます。これは、デッドスレッドの接続を見つけてそれらの接続を閉じるために使用されます。 –

+0

スレッドは、サーバー部分を実行するサービスが再起動または終了されたとき(つまり、JVMが終了したとき)にのみシャットダウンされます。実際には、私はそれらの接続をきれいにしないと私を殺しませんでした、と思います。スレッドの数は起動時に決定され、サーバーはランダムアイドルスレッドを選択し、必要なサービスを実行します。私の唯一の問題は、このスレッドプールは私のアプリケーションでは維持されていないが、いくつかのフレームワーク(他のアプリケーションでも使用されているので注意が必要です)です。 – Durandal

4

データベースソフトウェアによってはある程度の違いがあります。いくつかの(例えば、MySQL)は、比較的軽量の接続を持ち、速く開くことができます。オラクルのように、他の人たちは、深刻なオーバーヘッドを伴う大きなホンキング構造である接続を持っています。

一般的に、短い、大量のクエリでは、特にの接続プーリングを使用することをお勧めします。あなたのアプリには接続が含まれている方が早いほど、重要になります。これは過去数年間で変わっていません。もしあれば、アプリケーションが拡大してより複雑になるにつれて、これまで以上に重要になります。

確信が必要な場合は、ベンチマークを行うことをお勧めします。特定のケースでパフォーマンスのメリットが得られない場合は、おそらくそれは迷惑にならないでしょう。