2012-01-04 14 views
5

私は自分のiOSアプリケーションでSQLiteを使用しています。ユーザがUIとやりとりしている間に、たくさんのセーブ/ロードがあります。これは、UIが非常にやわらかくて遅くなるため、問題です。iOS SQLiteパフォーマンスが遅い

私は追加のスレッドで操作を実行しようとしましたが、これはSQLiteでは可能ではないと思います。私はそれを行う場合、私は頻繁にエラーコードSQLITE_BUSYとSQLITE_LOCKEDを取得します。

これらのエラーコードなしでマルチスレッドでこれを行う方法はありますか、またはSQLiteを放棄すべきですか?

+1

使用しているクエリを調整し、クエリプランを調べて、インデックスが必要かどうか確認しましたか? –

+2

複数の書き込みを行うときにトランザクションを使用していますか?あなたはすべきです - それは大きな違いをもたらします。 –

+0

Frederick Cheung:私は複数の書き込みと取り込みを使用しています。私はインデックス作成が助けになるかどうか見ていきますが、挿入するレコードがたくさんあるので、インデックス作成が役に立たないと思います。ホットリックス:私は複数の書き込みを使用するときにトランザクションを行っていません。私は同じロックを使用してデータベースのすべての書き込みのためにこれを行う必要がありますか? – VTS12

答えて

0

SQLiteを放棄しないでください。あなたは間違いなく遅いを避けるためにUIスレッドとは異なるスレッドでそれを行うことができます。ただスレッドが一度にデータベースにアクセスしていることを確認してください。同時アクセスを扱う場合、SQLiteはあまり役に立ちません。

+1

並行_reads_はうまくいきますが、_updates_は他のものをロックアウトします(DBレベルのロックよりも細かいものが複雑なため)。 –

+0

私の問題は、ユーザーがデータにアクセス/書き込みするときに制御できないことです。たとえば、あるビューではデータの読み込みと保存が行われますが、詳細をクリックしてデータを読み書きする新しいビューを押すこともできます。 1つのスレッドが同時にデータベースにアクセスすることをどのように確認できるかはわかりません。 – VTS12

3

バックグラウンドスレッドでSQLiteへのアクセスをシリアライズするだけで十分です。

私の答えはthis recent questionで私は正しい方向にあなたを指摘する必要がありますと思います。

他のところで述べたように、SQLiteは同時読み込みでは問題ありませんが、書き込みのためにデータベースレベルでロックします。つまり、異なるスレッドで読み書きしている場合は、SQLITE_BUSYおよびSQLITE_LOCKEDエラーが発生します。

これを回避するための最も基本的な方法は、ディスパッチキューまたはこのアクセスは、メインスレッド上で行われていないので1の並行性を持っているNSOperationQueueに(読み取りおよび書き込み)のいずれかにすべて DBアクセスをシリアライズすることですあなたのUIは影響を受けません。

これは明らかに重複した読み書きを停止しますが、同時に読み込みを停止します。それがあなたが取ることができるかどうかは、パフォーマンスヒットかどうかは明らかではありません。

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

[backgroundQueue setMaxConcurrentOperationCount:1]; 

あなたが合うように次に、あなただけのキューに操作を追加することができます。上記のようにキューを初期化するために

+0

私はこのようにやってみたが、まだエラーが発生した。私は今ディスパッチキューを使用しています。 – VTS12

+0

これですべてが正しく動作していますか?ディスパッチキューもうまくいくはずです。 – paulbailey

+0

いいえ、ディスパッチキューを使用した後、私は常にSQLITE_BUSYおよびSQLITE_LOCKEDエラーコードを取得しています。また、ビューのような奇妙な振る舞いが早期にポップされています。 – VTS12

0

OFF:FMDBそれはsqliteのラッパーで、スレッドセーフである:

あなたがチェックアウト持っています。私はすべてのsqliteプロジェクトで使用しました。

0

sqliteの上にあるCore Dataの使用をお勧めします。私はそれをマルチスレッド環境で使用します。 Concurrency with Core Dataに関するガイドがあります。

2

専用のSQLiteスレッド、または1度に1つずつの操作キューを持つことは、特に不安定なUIを解決するための優れた解決策です。別の手法(ジッタには役立たないかもしれません)は、これらのエラーコードを特定して、正常なリターンコードが得られるまで更新を再試行します。

1

SQLiteをWALモードにします。その後、読み取りはブロックされません。そうではありません - あなたはそれらを直列化する必要があります。それを達成する方法はいろいろあります。それらのうちの1つはSQLiteによって提供されます - WALフックは、次の書き込みが開始できることを知らせるために使用できます。

WALモードでは、通常、アプリのパフォーマンスが向上するはずです。ほとんどのものは少し速くなります。読み取りはまったくブロックされません。大規模なトランザクション(数MB)のみが減速します。一般的には劇的ではない。