2012-05-22 28 views
29

我一直花一些時間閱讀數據庫和SQLite的不同最佳實踐。在閱讀時,我發現自己做了很多事情,我不應該這樣做,當試圖解決這些問題時,在思考使用SQLite和ADO實現的一些細節時,我變得很困惑。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

我沒有確切地知道什麼是核心問題,但是如果問題是如何在很短的時間內在一個事務中插入批量插入語句。

這裏是一個輔助類,我發現較早,可以幫助你:

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

您發佈的鏈接似乎已被破壞。 (Chrome聲稱它是無止境的重定向循環) –

+0

當然,您可以在循環中使用插入行並調用flush後綴來提交事務,再次使用輔助鏈接:[SQLiteBulkInsertHelper.cs](https://docs.google.com/open?id = 0B5-wcgU-Ku-eMDNlY1R3SzByV00) –

+0

好的,謝謝你在評論中發佈的鏈接看起來很好我已經在你的文章中修復了它。 –

15

它有助於記住連接池和準備(編譯)語句只是有其限制的工具,沒有辦法可以同樣適用於所有可能的情況。記住這一點,讓我們記住何時可能想要使用連接池和準備好的語句。當連接是昂貴的,例如

可能願意使用連接池

連接池是有用的:

  • 這需要顯著時間建立連接(網絡連接到SQL服務器或Oracle數據庫),爲了提高系統性能,「緩存」打開的連接是有益的。
  • 連接是在應用程序(來自服務於多個併發請求的Web應用程序的連接)內或應用程序之間的有限和共享,因此必須儘快釋放它們以讓其他客戶端繼續。

可能原因使用預準備語句

準備語句只是旨在改善通過削減解析時可重複使用的查詢的性能。

SQLite:什麼是最佳選擇?

答案取決於您的應用需求。就個人而言,我不確定SQLite連接池是否是一個不錯的選擇。如果你的應用程序是單線程的,最好使用一個到SQLite數據庫的永久連接,這可能比池化速度快得多,並且也允許你使用準備好的語句。這與SQL Server的不同之處在於連接池是一個非常合理的默認設置。

如果性能很重要,您應該確定應用程序的配置文件,以查看SQLite連接池是否有利於您的場景。

具體問題

大部分的答案都與當前System.Data.SQLite提供商source

如果我打開和關閉我的連接(這可能會或可能並不意味着 連接被關閉以進行線程池),然後多少 使用我真的從一份聲明中得到些什麼?

通常,您應該將來自池的連接視爲新連接,即您不應期望從先前準備的語句中獲得任何好處。該聲明將被「重新編制」,除非您保留命令和連接。

但是我不相信我會看到在一個事務中保存單個 對象的好處,因爲一旦我關閉連接,這是從第一對象生成的 準備語句是現在 丟失。這是一個真實的陳述嗎?

這是一個真實的陳述。

如果我創建一個代表查詢,我會 執行很多時候我需要保持這種SQLiteCommand在內存中 準備好的聲明中保持活躍一個SQLiteCommand?

是的,你需要保留它。 SQLiteCommand持有對準備好的聲明的參考。

如果我創建一個具有相同的SQLite語句的新SQLiteCommand是 認識到,新SQLiteCommand是一樣的前面和 因而具有可以使用一份聲明中?

我不認爲這是支持。

如果我記得一個SQLiteCommand並改變它的參數和 連接,我打開和關閉不同的 交易的連接我在本質上保持一份聲明中不同的連接之間活着 ?

如果更改SQLiteCommand的連接,語句將被「重新準備」。

+0

使用預準備語句(特別是插入和更新)的一個非常重要的附加原因是爲了防止SQL注入攻擊。在所有情況下,準備好的語句正確地轉義了要存儲在數據庫中的值。 –