警告:以下に不正確な点があるかもしれません。私はこれに沿って多くのことを学んできたので、ひとつまみの塩でそれを取る。これはかなり長いですが、遊んでいたパラメーターを読んで、最後の結論にスキップできます。
SQLiteの書き込みパフォーマンスを心配できる多くのレイヤーがあります。
太字で強調されているものを見ました。特定のパラメーターは
- ディスク書き込みキャッシュ。最新のディスクには、回転ディスクに対するディスク書き込みを最適化するために使用されるRAMキャッシュがあります。これを有効にすると、データを順不同のブロックで書き込むことができるため、クラッシュが発生した場合、ファイルが部分的に書き込まれることになります。hdparm -W / dev / ...で設定を確認し、hdparm -W1 / dev / ...で設定します(オンにする場合、および-W0でオフにします)。
- barrier =(0 | 1)。「barrier = 0で実行する場合、ディスク書き込みキャッシュを有効にしないでください」というオンラインのコメントがたくさんあります。障壁に関する議論は、http://lwn.net/Articles/283161/にあります。
- data =(ジャーナル|注文|ライトバック)。これらのオプションの説明については、http://www.linuxtopia.org/HowToGuides/ext3JournalingFilesystem.htmlをご覧ください。
- commit = N。N秒ごとにすべてのデータとメタデータを同期するようにext3に指示します(デフォルトは5)。
- SQLiteプラグマsynchronous = ON | オフ。オンの場合、SQLiteは続行する前にトランザクションが「ディスクに書き込まれる」ことを確認します。これをオフにすると、基本的に他の設定はほとんど無関係になります。
- SQLiteプラグマcache_size。SQLiteがメモリ内キャッシュに使用するメモリ量を制御します。2つのサイズを試しました。1つはDB全体がキャッシュに収まるサイズで、もう1つはキャッシュが最大DBサイズの半分でした。
ext3ドキュメントでext3オプションの詳細をお読みください。
これらのパラメーターの多くの組み合わせでパフォーマンステストを実行しました。IDは、以下で参照されるシナリオ番号です。
シナリオ1として、マシンのデフォルト構成で実行することから始めました。シナリオ2は、「最も安全」であると想定したもので、適切な場合は、さまざまな組み合わせを試しました。これはおそらく私が使用することになったマップで理解するのが最も簡単です:
INTEGERのみ、TEXTのみ(ID列付き)、または混合のいずれかのテーブルで、挿入、更新、削除を含む多くのトランザクションを実行するテストスクリプトを作成しました。上記の各構成でこれを何度も実行しました。
下の2つのシナリオは#6と#17であり、「プラグマ同期=オフ」であるため、当然のことながら、それらは最速でした。3つの次のクラスターは、#7、#11、および#19です。これらの3つは、上記の「構成マップ」で青で強調表示されています。基本的に、構成はディスク書き込みキャッシュがオン、バリア= 0、およびデータが「ジャーナル」以外に設定されます。5秒(#7)と60秒(#11)の間でコミットを変更しても、ほとんど違いはありません。これらのテストでは、data = orderedとdata = writebackの違いがあまりないようでしたが、それは私を驚かせました。
混合更新試験は中央ピークです。このテストでは、明らかに明らかに遅いシナリオのクラスターがあります。これらはすべて、data = journalを持つものです。それ以外の場合、他のシナリオの間にはあまりありません。
別のタイミングテストがあり、さまざまなタイプの組み合わせで挿入、更新、削除のより異種混合が行われました。これらにはかなり時間がかかったため、上記のプロットには含めませんでした。
ここで、ライトバック構成(#19)は、順序付けられた構成(#7および#11)よりも少し遅いことがわかります。ライトバックは少し速くなると予想していましたが、おそらく書き込みパターンに依存するか、ext3でまだ十分に読み込めなかったのかもしれません:-)
さまざまなシナリオは、アプリケーションによって行われた操作をある程度代表しています。シナリオの候補リストを選んだ後、自動テストスイートのいくつかでタイミングテストを実行しました。これらは上記の結果と一致していました。
結論
- コミットパラメータ私たちは5秒であることを残しているので、少し違いを作るように見えました。
- ディスク書き込みキャッシュをオンにして、barrier = 0、data = orderedにします。これが悪い設定だと思ったものをオンラインで読んだり、多くの状況でこれがデフォルトであるべきだと思われる他のものを読んだ。最も重要なことは、あなたが何のトレードオフをしているのかを知って、情報に基づいた決定を下すことだと思います。
- SQLiteでは同期プラグマを使用しません。
- DBがメモリに収まるようにSQLite cache_sizeプラグマを設定すると、予想どおり、一部の操作のパフォーマンスが向上しました。
- 上記の構成は、少しリスクが大きいことを意味します。私たちは、使用することがありますSQLiteのバックアップAPIをスナップショットごとにNの分を取って、最後のMの周りを維持:部分書き込みのディスク障害の危険性を最小限にするために。パフォーマンステストを実行しながらこのAPIをテストしましたが、この方法を採用する自信がありました。
- それでももっと欲しい場合は、カーネルをいじくり回すことを検討できますが、そこに行かずに十分に改善しました。
@Huygensにさまざまなヒントとポインタを提供してくれてありがとう。