7

組み込みLinuxで実行しているアプリケーションがあります。いくつかのテーブルを備えたビルド済みのDBがあり、各テーブルには多数の行(数千)と52列があります。実行時に「INSERT」を実行するとディスクの断片化が発生するのではないかと心配しているため、事前にDBを構築しました。代わりに、多くのガベージ「INSERT」を使用して実行時に最初にDBを構築します。 'UPDATE'を使用します。

私は3秒ごとに大量のデータをDBに書き込んでいます。書き込み手順を高速化するために、SQLiteでWALモードを使用しています。しかし、私にはパフォーマンスの問題があります。チェックポイントが発生するたびに、時間がかかりすぎて、プロセッサが3秒未満でそれを実行できないようです。これを改善するために、10回の書き込み呼び出しのように、メインスレッドからチェックポイントよりもメッセージキューを受信するスレッドを作成しました。

だから今、状況は良くなっているように見えますが、WALファイルはどんどん大きくなっています...どうすればここで回避できますか?

4

2 に答える 2

7

断片化を回避し、データを事前に挿入する必要をなくすには、 SQLITE_FCNTL_CHUNK_SIZEsqlite3_file_control()とともにチャンクサイズを設定する必要があります。データベースファイルスペースを大きなチャンク(たとえば一度に1MB)に割り当てると、ファイルシステムの断片化が減り、パフォーマンスが向上します。Mozillaプロジェクトは現在、Firefox / Thunderbirdでこの設定を使用しており、大きな成功を収めています。

WALについて。大量のデータを頻繁に書き込む場合は、書き込みをより大きなトランザクションにラップすることを検討する必要があります。通常、すべてのINSERTは自動コミットされ、SQLiteはデータが実際にディスクまたはフラッシュにフラッシュされるまで待機する必要があります。これは明らかに非常に低速です。1つのトランザクションに複数の書き込みをラップする場合、SQLiteはすべての行を気にする必要がなく、一度に多くの行をフラッシュできます。ほとんどの場合、単一のフラッシュ書き込みになります。これははるかに高速です。したがって、可能であれば、少なくとも数百の書き込みを1つのトランザクションにラップするようにしてください。

私の経験では、フラッシュ上のWALはあまりうまく機能しておらず、古いジャーナルモードに固執する方が有益だと思います。たとえば、Android 4はSQLiteデータベースにWALモードを使用していませんが、これにはおそらく理由があります。お気づきのように、WALは状況によっては際限なく成長する傾向があります(ただし、トランザクションがめったにコミットされない場合にも発生します。そのため、時々そうするようにしてください)。

于 2012-11-19T09:32:53.953 に答える
2

WALモードでは、SQLiteは変更されたページを-walファイルに書き込みます。チェックポイントの間のみ、これらのページはデータベースファイルに書き戻されます。

-wal同時リーダーがない場合にのみ、ファイルを切り捨てることができます。

を呼び出したり実行sqlite3_wal_checkpoint_v2したりすることで、WALファイルを明示的にクリーンアップすることができますが、同時リーダーがある場合は失敗します。SQLITE_CHECKPOINT_RESTARTPRAGMA wal_checkpoint(RESTART)

于 2012-11-15T10:14:37.883 に答える