2012-05-22 27 views
29

私はデータベースとSQLiteのためのさまざまなベストプラクティスを読んでいました。読んでいるうちに、私がやってはいけないことがたくさんあることが判明しました。これらの問題を修正しようとすると、ADOの実装でSQLiteを使用する細かいディテールについて考えると混乱しました。SQLite/C#接続プーリングと準備文の混同

私の混乱は、特に準備文と接続プーリングに由来します。

http://msdn.microsoft.com/en-us/library/ms971481.aspxを読んでいるうちに、接続はトランザクションのためだけに開く必要があることがわかりました。トランザクションが完了したら、接続を終了する必要があります。なぜこれが当てはまるのかをしっかりと把握することはできませんが、私は作者がそれをよく知っているという前提で取り組んでいます。接続が閉じられると、実際には閉鎖されました。それは単にそれがプールに戻されたことを意味します。

私のクエリと挿入を改善するために、私はプリペアドステートメントの使用について読んでいます。 In SQLite, do prepared statements really improve performance?http://petesbloggerama.blogspot.com/2007/02/sqlite-adonet-prepared-statements.htmlはどちらも、準備されたステートメントが複数回実行されるクエリの実行時に実行されることを示しているようです。また、準備されたステートメントは接続に固有であり、接続が閉じられると準備されたステートメントは失われることも読んでいます。

私の混乱はこれです。私が接続を開いたり閉じたりしている場合(接続がスレッドプールのために閉じられていることを意味する場合もあれば、そうでない場合もあります)、準備されたステートメントから実際にどれだけの使用量が得られますか?私は1000のオブジェクトがある場合、私は準備されたステートメントが多くを助けることができる単一のトランザクションで保存する必要があることを理解することができます。しかし、接続を閉じると、最初のオブジェクトから生成されたプリペアドステートメントが失われるため、トランザクションで単一のオブジェクトを保存することによるメリットがあるとは思えません。これは真実な陳述ですか?

私の混乱は、準備されたステートメントが自分のSQLiteCommandオブジェクトのスコープにリンクされていると信じているという事実によります。

私は頻繁に実行されるクエリを表しSQLiteCommandを作成した場合、私はアクティブな滞在するプリペアドステートメントのためにメモリにそのSQLiteCommandを維持する必要がありますか?

私は同じSQLiteの文で新しいSQLiteCommandを作成した場合、それは新しいSQLiteCommandは前回と同じであるので、使用することができプリペアドステートメントを持っていることを認識しているのですか?

私はメモリにSQLiteCommandを維持し、私が開いて、別の取引のための接続を閉じるように、パラメータおよび接続の変更した場合、私は本質的に異なる接続間で生きてプリペアドステートメントを保管しておりますか!

私はこの時点で物事を考え超える可能性が高いですが、私はあなたが私はより良いこれらの事は、私はそれらのうちの最大の利益を得ることができますどのように相互作用するかを理解するのに役立つことを願って。

+2

私はSQLiteに精通していませんが、なぜあなたはすぐに接続を閉じるべきかに関しては、あなた自身が答えようとしています。基本的な物理接続は閉じられていません。その意味は、他のスレッドが使用できることです。接続にハングアップしても、実際には使用しない場合は、最大限の使用率が制限されることは明らかです。 (同じように、あなたがシングルスレッドのコンテキストであれば、接続プーリングはあまり意味がありませんが、多くのことを傷つけることはありません) –

答えて

0

Iは、コアの問題です正確に何をキャッチしていないが、問題がある場合はどのように少しの時間で1つのトランザクションで一括挿入文を挿入します。ここで

はあなたを助けることができる私は以前見つかったヘルパークラスである:

SQLiteBulkInsertHelper.cs

あなたはこのようにそれを使用することができます:あなたはとしてそれを見た場合

SQLiteBulkInsertHelper ContactBlk = new SQLiteBulkInsertHelper("<SQLiteConnection>","<Table Name>"); 
ContactBlk.AllowBulkInsert = true; 
ContactBlk.AddParameter("<Column Name>", /*Column Data Type*/System.Data.DbType.Int64); 
ContactBlk.AddParameter("<Column Name>", /*Column Data Type*/System.Data.DbType.String); 
ContactBlk.Insert(new object[] {<First Column Value>,<Second Column Value>}); 
ContactBlk.Flush(); 

はそれを試してみますあなたの問題に対する解決策。

+0

投稿したリンクが壊れているようです。 (クロムはそれが無限のリダイレクトループだと主張している) –

+0

もちろん、ループ内の挿入行を使用して、トランザクションをコミットするためにフラッシュ後の呼び出しを呼び出すことができます。ヘルパーリンク:[SQLiteBulkInsertHelper.cs](https://docs.google.com/open?id = 0B5-wcgU-Ku-eMDNlY1R3SzByV00) –

+0

あなたがコメントに投稿したリンクがあなたの投稿にも同様に修正されているようです。 –

15

接続プーリングと準備済み(コンパイル済み)の両方のステートメントは、制限があるツールに過ぎず、すべての可能な状況に同じようにアプローチすることはできません。これを念頭に置いて、いつ接続プーリングとプリペアドステートメントを使用するかを覚えておきましょう。

接続プーリングを接続プーリングを使用するための

考えられる原因接続は高価であるときなどに便利です:

  • これは、SQLへの接続(ネットワーク接続を確立するかなりの時間を要しサーバーまたはOracle DB)、システム・パフォーマンスを向上させるためにオープン接続を「キャッシュ」することが有益です。
  • 接続は(アプリケーションが複数の同時要求を処理するWebアプリケーションからの接続)またはアプリケーション間で制限され、共有されます。他のクライアントをできるだけ早く解放する必要があります。

    プリペアドステートメントは、単に解析時間を切り下げることで再利用可能なクエリのパフォーマンスを向上させるために意図されているプリペアドステートメントを使用するための

考えられる原因。

SQLite:ベストチョイスは何ですか?

答えはアプリケーションの要件によって異なります。個人的には、SQLite接続プーリングが必ずしも良い選択であるかどうかはわかりません。アプリケーションがシングルスレッドの場合、SQLite DBへの単一の永続的な接続を使用することが最善です。プーリングよりもはるかに高速であり、プリペアドステートメントも使用できます。これは、接続プーリングが非常に合理的なデフォルトであるSQL Serverとは異なります。

パフォーマンスが重要な場合は、アプリケーションをプロファイルして、シナリオでSQLite接続プーリングが有効かどうかを確認する必要があります。

固有の質問

回答のほとんどは、現在のSystem.Data.SQLiteプロバイダsourceに関連しています。

私はその後、私は本当にプリペアドステートメントからどのくらい 使用を取得しています(または を意味してもしなくてもよいの接続が原因スレッドプールに閉鎖されている)私の接続を開閉するのですか?

一般に、プールから出てくる接続を新しいものとして扱う必要があります。つまり、前に準備したステートメントから利益を得ることは期待できません。命令と接続の両方を保持しない限り、ステートメントは「再準備」されます。私は接続を閉じた後の最初のオブジェクトから生成された 準備文が今失わ あるので、私はトランザクションで単一 オブジェクトを保存から利益を見ることになるとは思わないしかし

。これは真実な陳述ですか?

これは真実です。

私は はしばしば私がアクティブに滞在し プリペアドステートメントのためにメモリにそのSQLiteCommandを維持する必要があります実行されるクエリを表しSQLiteCommandを作成した場合は?

はい、保存する必要があります。 SQLiteCommandは、準備されたステートメントへの参照を保持します。

私は同じSQLiteのステートメントを使用して新しいSQLiteCommandを作成した場合は、それは は新しいSQLiteCommandは前回と同じであることが認識されていると は、このように使用することができプリペアドステートメントを持っていますか?

私はそれがサポートされているとは思わない。

私はメモリにSQLiteCommandを維持し、変更した場合は、私が開くと、それはパラメータと 接続だ

と異なる 取引のための接続を閉じて、私は本質的に異なる接続間 生きてプリペアドステートメントを保管しておりますか!

SQLiteCommandの接続を変更すると、その文は「再準備されます」。

+0

特に挿入や更新のために準備されたステートメントを使用する非常に重要な理由は、SQLインジェクション攻撃を防ぐことです。準備されたステートメントは、すべての場合にデータベースに保存される値を適切にエスケープします。 –