SQLiteデータベースを照会するために既存のコードを改善するように求められました。元のコードはデータベースに対して複数回別々の呼び出しを実行し、Pythonで結果をフィルタリングしました。代わりに、データベース生成を再構築し、フィルタリングロジックをSQLクエリに入れることにしました。
さまざまなサイズのデータベースでベンチマークを実行した後。元の実装と比較して、n=3
新しい実装のクエリの平均クエリ時間がはるかに速いことがわかりました(3秒対46秒)。分)。キャッシュ問題のようですが、ソースが何であるかよくわかりません。各クエリ間でデータベース接続を閉じて、残りのPython変数を削除して実行しましたが、gc
この世界の外では状況が続きました。その後、おそらくシステムが何かをキャッシュしていることがわかりました。実際、各反復の後にシステムキャッシュをクリアすると、パフォーマンスecho 3 > /proc/sys/vm/drop_caches
は私の期待に合致します(80,000倍の速度向上に比べて2〜5倍の速度向上)。
今私が持っている最も哲学的な質問は、キャッシュパフォーマンス(現状のまま)または非キャッシュパフォーマンス(クエリの前に明示的にキャッシュを削除)という改善を報告する必要があるということです。 (おそらく両方を報告しますが、それでも何がキャッシュされるのか疑問に思います。)これは実際に何がキャッシュされるのかという質問につながると思います。つまり、キャッシュが実際のシナリオを表すのか、それともまったく表示しないのですか?
データベースまたはそのインデックスがキャッシュされている場合、高速な基本パフォーマンスは目に見えない新しいクエリで機能するため、実際の世界をうまく表現していると思います。ただし、特定のクエリをキャッシュする場合、まだ検証されていないクエリにはキャッシュパフォーマンスは反映されません。
注:これは重要ではない詳細かもしれませんが、このキャッシュの影響はfts5仮想テーブルを使用するときに特に顕著です!
要約:システムがSQLiteにクエリをキャッシュするとき、正確に何がキャッシュされ、これが見えない新しいクエリに良い影響を与えますか?
重要な場合:sqlite3を含むUbuntu 20.04。
答え1
いいえ、キャッシュされません。お問い合わせ。キャッシュするページ。
データベースはテーブル(およびインデックス)をページに保存します。各ページには1つ以上のテーブル行が含まれています。ページがキャッシュにある場合は、そのページの行が必要なすべてのクエリで使用できます。
インデックスにも同じです。新しいクエリに制限がある場合somefield between 20 and 40
(データベースエンジンが最初にキャッシュをチェックします)、キャッシュにその値の範囲を記述するそのインデックスのページが含まれていますか?
ページサイズは、新しいデータベースを作成するときに定義されます。 pragma ドキュメントを見るページサイズ制限事項と使用方法について説明します。
このアプローチを使用すると、関連していないクエリだけでなく、異なる接続間でもページを共有できます。どのように動作するかについてのドキュメントは次のとおりです。https://www.sqlite.org/sharedcache.html