2012-01-04 86 views
5

我在我的iOS應用中使用SQLite,當用戶與UI進行交互時,我有很多的保存/加載操作。這是一個問題,因爲它使界面非常緊張和緩慢。iOS SQLite性能低下

我試過在一個額外的線程中執行操作,但我不認爲這在SQLite中是可行的。如果我這樣做,我會經常得到錯誤代碼SQLITE_BUSY和SQLITE_LOCKED。

有沒有辦法在沒有這些錯誤代碼的多線程中做到這一點,還是應該放棄SQLite?

+1

您是否嘗試調整您使用的查詢並查看查詢計劃以查看是否需要任何索引? – 2012-01-04 12:56:32

+2

當您執行多次寫入時,您正在使用事務嗎?你應該 - 它會產生巨大的差異。 – 2012-01-04 12:57:21

+0

Frederick Cheung:我正在使用多次寫入和檢索。我會研究如果索引會幫助,但有很多記錄要插入,所以我不認爲索引會有幫助。熱舔:我使用多次寫入時沒有進行交易。我應該在數據庫中使用相同的鎖執行此操作嗎? – VTS12 2012-01-04 13:09:20

回答

0

不要放棄SQLite。你肯定可以在線程不同於線程的線程來避免緩慢。只要確保只有一個線程一次訪問數據庫。在處理併發訪問時,SQLite並不好。

+1

併發_reads_可以,但_updates_鎖定其他所有內容(由於比數據庫級鎖定更細粒度的任何事情)。 – 2012-01-04 12:58:12

+0

我的問題是我無法控制用戶何時訪問/寫入數據。例如,在一個視圖中,它將讀取並保存數據,但然後他們可以單擊細節並推送一個新的視圖,該視圖也將讀取/寫入數據。不知道如何確保一個線程同時訪問數據庫。 – VTS12 2012-01-04 13:12:46

3

這是完全可能的,你只需要在後臺線程中序列化對SQLite的訪問。

我在this recent question上的回答應該指出你認爲正確的方向。

正如其他地方提到的,SQLite適用於併發讀取,但在數據庫級別鎖定寫入。這意味着如果你正在讀寫不同的線程,你會得到SQLITE_BUSY和SQLITE_LOCKED錯誤。

最基本的方式,以避免這是連載所有 DB訪問(讀取和寫入)無論是在調度隊列或具有1的併發由於這種訪問是不是發生在主線程上的NSOperationQueue ,你的用戶界面不會受到影響。

這顯然會停止讀取和寫入重疊,但它也會停止同時讀取。目前還不清楚這是否會帶來性能下降。

NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init]; 

[backgroundQueue setMaxConcurrentOperationCount:1]; 

然後,你可以添加操作到隊列中,你認爲合適:

爲了如上所述初始化的隊列。

+0

我試過這樣做,仍然遇到錯誤。我現在使用一個調度隊列。 – VTS12 2012-01-04 13:08:53

+0

你現在一切正常嗎?派遣隊列也應該沒問題。 – paulbailey 2012-01-04 13:11:09

+0

不,使用派遣隊列後,我不斷地收到SQLITE_BUSY和SQLITE_LOCKED錯誤代碼。此外,怪異的行爲,如意見被提前彈出等。 – VTS12 2012-01-04 13:13:51

0

OFF:

你有沒有籤:FMDB它是一個sqlite的包裝,是線程安全的。我用它在我所有的sqlite項目中。

2

將所有東西放在專用的SQLite線程中,或者一次只能運行一次的操作隊列都是很好的解決方案,特別是解決您的不安用戶界面。另一種技術(可能無助於抖動)是爲了發現這些錯誤代碼,並簡單地循環,重試更新,直到獲得成功的返回代碼。

1

將SQLite置於WAL模式。然後讀取將不會被阻止。不這麼寫 - 你需要序列化它們。如何實現它有很多種方法。其中一個是由SQLite提供的--WAL鉤子可以用來表示下一次寫入可以開始。

WAL模式通常應該可以提高應用程序的性能。大部分事情會快一點。讀取將不會被阻止。只有大型交易(幾MB)會放緩。一般沒什麼戲劇性