このセクションでは、クエリーキャッシュが動作可能な場合のその仕組みについて説明します。セクション8.9.3.3「クエリーキャッシュの構成」では、それを動作可能にするかどうかを制御する方法について説明しています。
受信したクエリーは、解析前にクエリーキャッシュにあるそれらと比較されるため、次の 2 つのクエリーは、クエリーキャッシュによって異なるものとみなされます。
SELECT * FROM tbl_name
Select * from tbl_name
クエリーは、同一とみなされるためには、正確に同じ (バイトごと) である必要があります。さらに、ほかの理由で、同一のクエリー文字列が異なるものとして扱われることもあります。異なるデータベース、異なるプロトコルバージョン、または異なるデフォルトの文字セットを使用するクエリーは、異なるクエリーとみなされ、別々にキャッシュされます。
次の種類のクエリーにはキャッシュが使用されません。
外部クエリーのサブクエリーであるクエリー
ストアドファンクション、トリガー、またはイベントの本体内で実行されるクエリー
クエリー結果をクエリーキャッシュからフェッチする前に、MySQL は、関連するすべてのデータベースとテーブルに対して、ユーザーが SELECT
権限を持っているかどうかをチェックします。これが当てはまらない場合、キャッシュ結果は使用されません。
クエリー結果がクエリーキャッシュから返される場合、サーバーは Com_select
ではなく Qcache_hits
ステータス変数を増やします。セクション8.9.3.4「クエリーキャッシュのステータスと保守」を参照してください。
テーブルが変更された場合、そのテーブルを使用するキャッシュされたすべてのクエリーが無効になり、キャッシュから削除されます。これには、変更されたテーブルにマップされた MERGE
テーブルを使用するクエリーも含まれます。テーブルは、INSERT
、UPDATE
、DELETE
、TRUNCATE TABLE
、ALTER TABLE
、DROP 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.7.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) またはストアドファンクションを参照している。
それがユーザー変数またはローカルに保存されたプログラム変数を参照している。
それが
mysql
、INFORMATION_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
テーブルを使用している。それがどのテーブルも使用していない。
それが警告を生成する。
ユーザーが関連するすべてのテーブルのカラムレベルの権限を持っている。