web-dev-qa-db-ja.com

データベース接続の作成-1回実行するか、クエリごとに実行しますか?

現時点では、Webページが最初に読み込まれたときにデータベース接続を作成します。次に、ページを処理し、その接続に対してクエリを実行します。これは最良の方法ですか、それともクエリを実行するたびにデータベース接続を作成する必要がありますか?

p.s 1つの接続を作成して使用する方が理にかなっていますが、これが他の問題を引き起こす可能性があるかどうかはわかりません。

MSSQLでC#(ASP.NET)を使用しています。

119
webnoob

クエリ/トランザクションごとに1つ作成すると、接続の「クローズ」の管理がはるかに簡単になります。

常識的な理由から、1つを開いて使用するように指示されているのはわかりますが、接続の切断やマルチスレッド化で問題が発生します。したがって、次のステップは、プール(たとえば50)を開き、それらをすべて開いたままにして、さまざまなプロセスに割り当てます。そして、あなたはそれを見つけるでしょう これはまさに.NETフレームワークがあなたのためにすでにしていることです

必要なときに接続を開き、完了時に破棄すると、実際には接続が閉じられず、接続プールに戻されて再び使用されます。

139
pdr

クエリごとに1つの接続を作成することをお勧めします。データを表示する場合、クエリに必要なデータをallで取り込むことをお勧めします。一行。

背景情報:

.NETでは、SqlConnection.Open()を呼び出すと、デフォルトで常に 接続プール が透過的に使用されます(MSDNの "SQL Serverでの接続プールの使用" を参照)。したがって、Open()を使用して新しい接続を取得し、完了したらClose()を呼び出すだけで、.NETが正しく動作します。

接続プールがない場合、実際のデータベース接続の作成は非常にコストがかかる可能性があり(認証、ネットワークオーバーヘッドなど)、同時オープン接続の数は通常非常に制限されるため、クエリごとに1つの接続は非常に悪い考えです。

39
Oded

開発者は、接続オブジェクトを再利用するためにコードを「最適化」したい場合があります。この質問のコンテキストが.Netエコシステムにいることを考えると、これはほとんどの場合間違いです。 (注:他の多くのプラットフォームでも同様に処理されます)。

ADO.NetにはConnection Poolingという機能があります。新しい接続オブジェクトを作成して開くと、実際に行っているのはプールからの接続を要求することです。接続を閉じると、プールに戻ります。

コードで直接使用するオブジェクトを理解することが重要です。SqlConnection、MySqlConnection、OleDbConnectionなどは、ADO.NetとADOによって管理される実際の基になる接続を囲むラッパーです.Netの実際の接続は、パフォーマンスの観点から見ると、はるかに「重く」、高価です。認証、ネットワーク通過、暗号化などの心配があるのはこれらの基礎となるオブジェクトであり、これらは、実際のコードで実際に表示されるオブジェクトの少量のメモリをはるかに上回ります。

接続オブジェクトを再利用しようとすると、能力を壊すため、はるかに大きなものを犠牲にして、小さなもので効率を上げます ADO.Netが重要な基礎となる接続を効果的に管理するために。

アプリケーションまたはhttpリクエスト全体で接続を再利用すると、並行して実行できる可能性のある何かを誤ってシリアル化し、パフォーマンスのボトルネックになる可能性もあります。これが実際のアプリケーションで発生するのを見てきました。

このWebページの例の場合、少なくとも1つのhttpリクエスト/レスポンスの期間中は小さな接続のみを維持するため、リクエストパイプラインで実行するクエリを評価してさらに効率を上げることができます。データベースへの個別のリクエストをできるだけ少なくします(ヒント:単一のSQL文字列で複数のクエリを送信し、DataReader.NextResult()を使用するか、DataSetの異なるテーブルをチェックしてそれらの間を移動します)。

言い換えれば、アプリケーションまたはhttpリクエストに対して1つの接続を再利用するか、クエリごとに1つの接続を再利用するかではなく、データベースを呼び出すたびに1つの接続、つまり各ラウンドトリップについて考えます。次に、それらのトリップの数を最小化することにより、接続の数を最小化しようとします。このようにして、両方の目標を満たすことができます。


ただし、これは1種類の最適化にすぎません。プログラマーの時間を最適化し、効果的なコードを再利用することもできます。開発者は、オープンですぐに使用できる接続オブジェクトを取得するためだけに、同じボイラープレートコードを何度も書きたくありません。これは退屈なだけでなく、プログラムにバグを導入する方法でもあります。

ただし、ここでも、クエリ(または往復)ごとに1つの接続を使用する方が一般的にはましです。データベースへの呼び出しごとに1つの接続という目標を維持しながら、同じボイラープレートコードを書き直すことを回避するために使用できるパターンがあります。 これは1つの例です 好きですが、他にもたくさんあります。

2
Joel Coehoorn