頻繁なクエリキャッシュの無効化のオーバーヘッドは価値がありますか?


22

現在、主に多くのテーブルで実行されているINSERT、DELETE、UPDATEステートメントの数が多いため、クエリキャッシュから多数の無効化が発生しているMySQLデータベースで作業しています。

私が判断しようとしているのは、これらのテーブルに対して実行されているSELECTステートメントにクエリキャッシュを使用できるようにすることの利点があるかどうかです。それらは非常に迅速に無効化されるため、これらのテーブルのSELECTステートメントでSQL_NO_CACHEを使用することが最良の方法であると思われます。

頻繁な無効化のオーバーヘッドは価値がありますか?

編集:以下のユーザー@RolandoMySQLDBAのリクエストに応じて、MyISAMおよびINNODBに関する情報を以下に示します。

InnoDB

  • データサイズ:177.414 GB
  • インデックスサイズ:114.792 GB
  • テーブルサイズ:292.205 GB

MyISAM

  • データサイズ:379.762 GB
  • インデックスサイズ:80.681 GB
  • テーブルサイズ:460.443 GB

追加情報:

  • バージョン:5.0.85
  • query_cache_limit:1048576
  • query_cache_min_res_unit:4096
  • query_cache_size:104857600
  • query_cache_type:ON
  • query_cache_wlock_invalidate:オフ
  • innodb_buffer_pool_size:8841592832
  • 24GBのRAM

2
dom.as/tech/query-cache-tuner合計かなりうまくそれまで
Laurynas Biveinis

へへ、非常に洞察力に富んだ。
クレイグセフトン

回答:


16

あなただけでクエリキャッシュを無効にする必要があります

[mysqld]
query_cache_size = 0

その後、mysqlを再起動します。なぜ私はそれを提案するのですか???

クエリキャッシュは、常にInnoDBに突き当たります。変更が他のトランザクションの反復可能な読み取りに影響しない場合、InnoDBのMVCCがクエリキャッシュからクエリを提供できるようにすると便利です。残念ながら、InnoDBはそれを行いません。どうやら、かなり早く無効化され、おそらく再利用されないクエリがたくさんあります。

MySQL 4.0のInnoDBの場合、クエリキャッシュはトランザクションに対して無効にされていました。MySQL 4.1+の場合、テーブルごとにクエリキャッシュへのアクセスを許可すると、InnoDBはトラフィック警官を再生します。

あなたの質問の観点から、クエリキャッシュを削除する正当化はオーバーヘッドではなく、InnoDBがどのように管理するかということです。

InnoDBがクエリキャッシュと対話する方法の詳細については、書籍「High Performance MySQL(Second Edition)」の 213-215ページを参照してください。

データのすべてまたは大部分がMyISAMである場合、SQL_NO_CACHEを使用するという元のアイデアを使用できます。

InnoDBとMyISAMが混在している場合、キャッシュミスの大きさに基づいて、アプリケーションに適切なバランスを見つける必要があります。実際、同じ本のページ209-210はキャッシュミスの理由を指摘しています:

  • クエリには、非決定的な構造(CURRENT_DATEなど)が含まれているか、結果セットが大きすぎて格納できないため、クエリはキャッシュできません。
  • サーバーは以前にクエリを見たことがないため、結果をキャッシュする機会がありませんでした。
  • クエリの結果は以前にキャッシュされましたが、サーバーはそれを削除しました。これは、それを保持するのに十分なメモリがなかった、誰かがサーバーにそれを削除するように指示した、または無効にされたために発生する可能性があります

キャッシュできないクエリがほとんどない場合のキャッシュミスの根本的な原因は次のとおりです。

  • クエリキャッシュはまだウォームではありません。これは、サーバーが結果セットでキャッシュを埋める機会がなかったことです。
  • サーバーは、これまでに見たことのないクエリを見ています。クエリの繰り返しが多くない場合は、キャッシュがウォームアップされた後でも発生する可能性があります。
  • 多くのキャッシュ無効化があります。

更新2012-09-06 10:10 EDT

最新の更新情報を見ると、query_cache_limit1048576(1M)に設定されています。これにより、結果セットが1Mに制限されます。より大きなものを取得した場合、単にキャッシュされません。あなたがきているがquery_cache_size104857600(100M)に設定され、これが唯一の完璧な世界に設定された100のキャッシュされた結果が可能になります。何百ものクエリを実行すると、断片化がかなり早く発生します。また、最小サイズの結果セットとして4096(4K)があります。残念ながら、mysqlにはクエリキャッシュを最適化するための内部メカニズムがありません。

クエリキャッシュが必要で、RAMが非常に多い場合は、次を実行できます。

SET GLOBAL query_cache_size = 0;
SELECT SLEEP(60);
SET GLOBAL query_cache_size = 1024 * 1024 * 1024;

クエリキャッシュをパージするため。キャッシュされた結果はすべて失われるため、これらの行はオフピーク時に実行してください。

また、次のものを割り当てます。

  • query_cache_size = 1G
  • query_cache_limit = 8M

これにより、23GのRAMが残ります。私は以下を提起します:

  • innodb_buffer_pool_size = 12G
  • key_buffer_size = 4G

7Gが残ります。これは、OSおよびDB接続に十分なはずです。

キーバッファーはMyISAMインデックスページのみをキャッシュし、InnoDBバッファープールはデータとインデックスをキャッシュすることに注意してください。

もう1つの推奨事項:MySQL 5.5にアップグレードして、複数のCPUと読み取り/書き込みI / Oの複数のスレッド用にInnoDBを構成できるようにします。

InnoDBの複数のCPUへのアクセスと併せてMySQL 5.5を使用することに関する以前の投稿を参照してください。

更新2012-09-06 14:56 EDT

クエリキャッシュをクリアする私の方法は、キャッシュされたデータをホースし、RAMの完全に異なるセグメントを形成するため、かなり極端です。あなたがコメントで指摘したように、FLUSH QUERY CACHE(あなたが提案したように)またはさらにRESET QUERY CACHE良いでしょう。明確にするために、「内部メカニズムなし」と言ったとき、私はまさにそれを意味していました。最適化が必要であり、手動で行う必要があります。crontab'dする必要があります

MyISAMよりもInnoDBでDML(INSERT、UPDATE、DELETE)を頻繁に行う場合、最初に言ったように、クエリキャッシュを完全に削除すると言います。


回答ありがとうございます。私はその本を持っており、広範囲に使用しています。キャッシュミスの概要を説明しますが、前述のように、Com_selectとQcache_insertsの間に強い相関関係があるため、キャッシュの無効化が重要な問題であると既に特定しています。ああ、問題のDBにはINNODBとMyISAMが混在しています。
クレイグセフトン

リクエストした追加情報で更新されました。ありがとう。
クレイグセフトン

回答をありがとう、私は残りを楽しみにしています。確認したことの1つは、クエリの約18%がキャッシュされていないことでした。そのため、設定に関するアドバイスに間違いなく感謝しています。残念ながら、このボックスは専用ではありませんが、推奨事項が役立つはずです。フラグメンテーションも間違いなく問題です。まだキャッシュされていないクエリとは対照的に、私たちが目にしている無効化の数を本当に心配しています。あなたの洞察に本当に感謝します、どうもありがとう。
クレイグセフトン

「mysqlにはクエリキャッシュを最適化するための内部メカニズムがありません」に関するコメントについて、最適化するコマンドFLUSH QUERY CACHEを実行できませんか?参照:dev.mysql.com/doc/refman/5.0/en/flush.html
クレイグセフトン

回答を更新しました
...-RolandoMySQLDBA

3

悪い例:query_cache_size = 1G

どうして?フラッシュにかかる時間のため。つまり、何らかの書き込みが発生すると、1GB全体がスキャンされ、変更されたテーブルへの参照が検出されます。QCが大きいほど、これは遅くなります。データがほとんど変更されない限り、サイズは50M以下にすることをお勧めします。

QCはMyISAMとInnoDBの両方のオーバーヘッドです。グローバルMutexを取り出し、すぐに取り出します。このミューテックスは、MySQLが約8コア以上を効果的に使用できない理由の1つです。

SQL_NO_CACHEはまで気づいていませんミューテックスがロックされています!そのフラグの唯一の用途は、ベンチマークのためです。

多くの場合、RAMを他のキャッシュに割り当てることをお勧めします。


2

私はそれのための完璧なケースを考えることができ、私たちは徹底的にテストし、本番環境で実行しました...私はそれを「高速レーン」クラスタリング戦略と呼んでいます:

MaxScaleなどのプロキシを使用して読み取り/書き込み分割を行う場合、またはアプリケーションに対応している場合、クエリキャッシュが有効になっているスレーブにのみ無効なテーブルの読み取りを送信し、残りはそれを使用する他のスレーブに送信できますオフにしました。

これを実行し、結果として、負荷テスト(ベンチマークではなく実際の取引)中にクラスターへの1分あたり4Mの呼び出しを処理します。アプリはいくつかのことをmaster_pos_wait()で待機するため、レプリケーションスレッドによって調整され、非常に高いスループットでQcacheの無効化を待機するステータスで確認しましたが、これらのスループットレベルはクラスターよりも高くなっていますQcacheなしで機能します。

これが機能するのは、これらのマシンの小さなクエリキャッシュに無効化するものがほとんどないためです(これらのクエリは、頻繁に更新されないテーブルにのみ関連します)。これらのボックスは「高速レーン」です。アプリケーションが実行する残りのクエリについては、Qcacheを有効にせずにボックスに移動するため、Qcacheと競合する必要はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.