Documentation Home
MySQL 5.6 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 27.1Mb
PDF (A4) - 27.2Mb
HTML Download (TGZ) - 7.2Mb
HTML Download (Zip) - 7.2Mb


8.9.3.1 クエリーキャッシュの動作

このセクションでは、クエリーキャッシュが動作可能な場合のその仕組みについて説明します。セクション8.9.3.3「クエリーキャッシュの構成」では、それを動作可能にするかどうかを制御する方法について説明しています。

受信したクエリーは、解析前にクエリーキャッシュにあるそれらと比較されるため、次の 2 つのクエリーは、クエリーキャッシュによって異なるものとみなされます。

SELECT * FROM tbl_name
Select * from tbl_name

クエリーは、同一とみなされるためには、正確に同じ (バイトごと) である必要があります。さらに、ほかの理由で、同一のクエリー文字列が異なるものとして扱われることもあります。異なるデータベース、異なるプロトコルバージョン、または異なるデフォルトの文字セットを使用するクエリーは、異なるクエリーとみなされ、別々にキャッシュされます。

次の種類のクエリーにはキャッシュが使用されません。

  • 外部クエリーのサブクエリーであるクエリー

  • ストアドファンクション、トリガー、またはイベントの本体内で実行されるクエリー

クエリー結果をクエリーキャッシュからフェッチする前に、MySQL は、関連するすべてのデータベースとテーブルに対して、ユーザーが SELECT 権限を持っているかどうかをチェックします。これが当てはまらない場合、キャッシュ結果は使用されません。

クエリー結果がクエリーキャッシュから返される場合、サーバーは Com_select ではなく Qcache_hits ステータス変数を増やします。セクション8.9.3.4「クエリーキャッシュのステータスと保守」を参照してください。

テーブルが変更された場合、そのテーブルを使用するキャッシュされたすべてのクエリーが無効になり、キャッシュから削除されます。これには、変更されたテーブルにマップされた MERGE テーブルを使用するクエリーも含まれます。テーブルは、INSERTUPDATEDELETETRUNCATE TABLEALTER TABLEDROP TABLE、または DROP DATABASE などの多くの種類のステートメントによって変更できます。

InnoDB テーブルを使用する際のトランザクション内でもクエリーキャッシュは機能します。

MySQL 5.6 では、ビュー上の SELECT クエリーからの結果がキャッシュされます。

クエリーキャッシュは、SELECT SQL_CALC_FOUND_ROWS ... クエリーに対して機能し、後続の SELECT FOUND_ROWS() クエリーで返される値を格納します。FOUND_ROWS() は前のクエリーがキャッシュからフェッチされている場合でも、見つかった行の数もキャッシュに格納されているため、正確な値を返します。SELECT FOUND_ROWS() クエリー自体はキャッシュできません。

mysql_stmt_prepare() および mysql_stmt_execute() を使用し、バイナリプロトコルを使用して発行されたプリペアドステートメント (セクション23.8.8「C API プリペアドステートメント」を参照してください) はキャッシュが制限されます。クエリーキャッシュ内のステートメントとの比較は、? パラメータマーカーの拡張後のステートメントのテキストに基づきます。ステートメントは、バイナリプロトコルを使用して実行されたほかのキャッシュされたステートメントとのみ比較されます。つまり、クエリーキャッシュの目的で、バイナリプロトコルを使用して発行されたプリペアドステートメントは、テキストプロトコルを使用して発行されたプリペアドステートメント (セクション13.5「準備済みステートメントのための SQL 構文」を参照してください) と区別されます。

クエリーに次の表に示すいずれかの関数が含まれる場合、クエリーはキャッシュできません。

AES_DECRYPT() (5.7.4 現在) AES_ENCRYPT() (5.7.4 現在) BENCHMARK()
CONNECTION_ID() CONVERT_TZ() CURDATE()
CURRENT_DATE() CURRENT_TIME() CURRENT_TIMESTAMP()
CURTIME() DATABASE() 1 つのパラメータを持つ ENCRYPT()
FOUND_ROWS() GET_LOCK() LAST_INSERT_ID()
LOAD_FILE() MASTER_POS_WAIT() NOW()
PASSWORD() RAND() RANDOM_BYTES()
RELEASE_LOCK() SLEEP() SYSDATE()
パラメータを持たない UNIX_TIMESTAMP() USER() UUID()
UUID_SHORT()    

次の条件下のクエリーもキャッシュされません。

  • それがユーザー定義関数 (UDF) またはストアドファンクションを参照している。

  • それがユーザー変数またはローカルに保存されたプログラム変数を参照している。

  • それが mysqlINFORMATION_SCHEMA、または performance_schema データベース内のテーブルを参照している。

  • (MySQL 5.6.5 以降:) それがパーティション化されたテーブルを参照している。

  • それが次のいずれかの形式である。

    SELECT ... LOCK IN SHARE MODE
    SELECT ... FOR UPDATE
    SELECT ... INTO OUTFILE ...
    SELECT ... INTO DUMPFILE ...
    SELECT * FROM ... WHERE autoincrement_col IS NULL

    最後の形式は、最後の挿入 ID 値を取得するための ODBC の回避方法として使用されるため、キャッシュされません。第23章「Connector および APIの Connector/ODBC のセクションを参照してください。

    SERIALIZABLE 分離レベルを使用するトランザクション内のステートメントは LOCK IN SHARE MODE ロックを使用するため、それらもキャッシュできません。

  • それが TEMPORARY テーブルを使用している。

  • それがどのテーブルも使用していない。

  • それが警告を生成する。

  • ユーザーが関連するすべてのテーブルのカラムレベルの権限を持っている。


User Comments
  Posted by Vlatko Šurlan on July 5, 2010
A nice little treatise on MySQL Query Cache with some nasty gotchas and tricks that might shave a few days off of your 'what the heck is going wrong here' time: http://www.docplanet.org/mysql/mysql-query-cache-in-depth/
Sign Up Login You must be logged in to post a comment.