2017-06-23 10 views
0

私はそれに約700万行のテーブルを持っています。私はデータベースに毎秒約1行を平均で挿入しています。これを行うと、データベースに対して簡単なSELECTを実行するには非常に長い時間(15秒程度)かかることに気づいています。SQLiteは最近の挿入が行われたときに非常に遅く選択します

SELECT * FROM table WHERE rowid > 7100000 

この選択は、この特定のテーブルにデータが挿入されていないことがあるため、多くの場合、データ行を返しません。私が書いているテーブルが、私が読んでいるテーブルに実際に行を挿入していないときでさえ、しばしば起こっています。

2つのプロセスがあり、1つはデータを追加し、もう1つはまだ読み取られていないすべての新しいデータを取得することです。しかし、読み取り側はUIに接続されており、目立つラグは耐えられず、15秒以下です。これはAndroidの下で実行されており、UIスレッドはその間ブロックされていないようで、混乱を招いています。

私の最初の考えは、元々は別のフィールド(時間フィールド)にインデックスを持っていたので、インサートがインディケータの更新を必要としていた可能性があります。これは少なくとも部分的に確認されたようですが、私はわずか数行のデータベースを使用すると、各選択は数ミリ秒で完了します。しかし、プライマリ・キーとしてのROWIDしか持たないようにテーブルを再作成すると、実際には遅くなりました。私は最後に新しい行を挿入すると、主キーとしてのROWIDを比較すると、常に非常に高速な読み込みが行われることが予想されます。

先読みログを有効にしようとしましたが、SQLCipherはこれをサポートしていません。少なくとも、直接的ではありません。これは、android.database.sqlite.SQLiteDatabaseの最新のAPIに準拠していないためです。 postkeyフックで "PRAGMA journal_mode = WAL"を使っても、何の違いもありません。

ここでは何が起こっていますか?どのように選択をスピードアップできますか?

更新:私はsqlcipherを取り除き、それが要素だったかどうかを見るために単純なsqliteを使用してみました。 sqlcipher_exportを使用して平文データベースにエクスポートし、デフォルトのandroid.database.sqlite.SQLCipherを使用しました。遅延時間は10-20秒から1.8-2.8秒に減少した。その後、先読みを取り除き、さらに1.3-2.7sに下がった。それで問題はまだ目立っていますが、それはずっと良くなっています。

+0

まず、アプリケーションに対する同時挿入の影響とクエリの影響を特定します。つまり、新しいデータの挿入を無効にし、同じselect文の実行時間を測定します。また、一度に挿入される行の数と、その操作がトランザクション内で実行されているかどうかを確認すると便利です。 –

答えて

0

SQLiteは最終的にはファイルベースであり、ファイルの一部が変更された別のプロセスと通信するための移植可能なメカニズムはありません。したがって、あるプロセスが何かを書き込んだ場合、他のすべてのプロセスは、次回にデータベースファイルにアクセスするときにキャッシュを削除する必要があります。

可能であれば、コードの両方の部分が同じプロセスにあり、同じデータベース接続を共有するアーキテクチャを変更してください。 (複数のスレッドを使用する場合はロックが必要ですが、SQLiteの同時実行性はあまりありません)

新しいデータを別のデータベースに書き込み、

なぜSQLCipherが非常に遅いのか分かりません(復号化のCPUオーバーヘッドにはなりません)。

関連する問題