web-dev-qa-db-ja.com

SQL_NO_CACHEを使用したクエリの初回実行時の速度が低下するのはなぜですか?

クエリは、selectのSQL_NO_CACHE 1limit 1のみを使用して、可能な限り高速になるように作成されています。結果はかなり興味深いものです。最初の実行では、0.125-0.203秒かかります。通常、次の実行はすべて0.040秒未満です。それは一種のウォームアップですか、それともクエリプロセスの構築に関連していますか?

今のところ問題ではありませんが、なぜそうなのかを知り、できれば避けたいです。

エンジン-InnoDB
MySQLバージョン-5.6で5.7としてテスト済み

4
Grokking

別の答えが強調されているように、クエリキャッシュは唯一のキャッシュではありません。ほとんどの場合、その使用はお勧めできません-実際、MySQL 8.0で削除されました。その理由は、スケーラビリティの問題(グローバルロックによって制御される)があり、データが頻繁に無効になるため、通常のワークロードで使用できないためです。

ただし、InnoDBバッファープールには、頻繁にアクセスされるインデックスとデータが含まれています。最初のクエリの後、一部のインデックスとデータがキャッシュされるため、次回はメモリから読み込まれます。おそらく一部のデータ/インデックスページはクエリごとに1回だけアクセスされます。その場合、2回目と3回目の実行の間にわずかな違いが見られるはずです(これらのページが初めてキャッシュされないとき)。

クエリ実行時間の違いを回避するにはどうすればよいですか?さて、ディスクから読み取る必要があるため、クエリの初回実行時にクエリを高速化する方法はありません。ただし、バッファプールが十分に大きい場合、クエリは常に高速になります。大きなバッファプールはMySQLのパフォーマンスにとって非常に重要であることを覚えておいてください。一般的な推奨事項は、総メモリの75〜80%を維持することです。しかし実際には、物事はより複雑です:

  • 他のキャッシュとバッファにはスペースが必要です。特に、多数のユーザーがいる場合、またはユーザーが多数のJOINまたはORDER BYを実行している場合は、セッションごとのバッファーを考慮する必要があります。
  • バッファプールをデータベースより大きくしても意味がありません。そして、一般的に、それをホットデータ(頻繁にアクセスするデータ)よりも大きくすることは無駄です。

もう1つは、すべてのサーバーが再起動されることがあります。この場合、バッファプールが単に空になっていると、再起動後、ホットデータが再度キャッシュされるまでクエリが遅くなります。ただし、次のように設定することでこれを回避できます。

innodb_buffer_pool_dump_at_shutdown = 1
innodb_buffer_pool_load_at_startup = 1

このようにして、バッファープールはシャットダウン時に(部分的に)ディスクに書き込まれ、起動時に再ロードされるため、再起動後でもクエリは高速になります。

1

クエリキャッシュは、クエリに含まれるいくつかのキャッシュの1つにすぎません。さらに重要なのは バッファプール であり、ファイルシステムから読み込まれたブロックをキャッシュします。

最初のクエリでは、クエリで使用されるテーブル行やインデックスを含むブロックを実際のディスクからフェッチする必要があります。それ以降は、それらはバッファキャッシュに置かれ、後続のクエリでそれらが見つかります。

MySQLのバッファキャッシュは、実際にはファイルシステムのブロックキャッシュの上の薄い層であると推測します。 Linuxで実行している場合は、次のコマンドを実行してキャッシュを削除できます。これはバッファキャッシュ自体を変更しませんが、次にキャッシュがアクセスされるときにファイルシステムにブロックを再ロードさせる必要があります。

Sudo echo 3 > /proc/sys/vm/drop_caches

インターネットで見つけた「Sudo」コマンドと同様に、盲目的に実行する前にこれを調査する必要があります。

0
guest