このセクションは、クエリ キャッシュのメカニズムを説明します。設定方法は、項4.13.3. 「クエリ キャッシュの設定」 を参照してください。
解析前のクエリには、解釈が始まる前にクエリ キャッシュにあるクエリとの照合を行います。そのため、次の 2 つのクエリは、クエリ キャッシュで異なるものである、とみなします。
SELECT * FROMtbl_name
Select * fromtbl_name
クエリは、バイト同士など、完全に一致する しない限り、同一とは判断しません。たとえば、クライアントで新しい形式の通信プロトコルを使用している場合や、別のクライアントが使用しているものとは異なるキャラクタセットを使用している場合も、同じものであるはずのクエリが異なるものとして、認識することがあります。
クエリ キャッシュは、解釈が始まる前にクエリ同士を照合することから、次のような種類のクエリはキャッシュの対象になりません。
準備されたステートメント (準備文)
クエリが外部クエリのサブクエリである場合
Stored プロシージャ、Stored 関数、トリガ、イベントなどのボディ内で実行したクエリ
クエリ結果をキャッシュからフェッチする前に、MySQL
で、そのユーザがすてべのデータベースと関連するテーブルにおいて、
SELECT
権限があるかどうかを調べます。権限がない場合は、キャッシュ結果は使用しません。
クエリ結果がキャッシュから返る度に、サーバは
Qcache_hits
システム変数の値を増加します。Com_select
ではありません。詳細は
項4.13.4. 「クエリ キャッシュのステータスと保守」
を参照してください。
テーブルに変更があった場合、そのテーブルからキャッシュしたクエリのすべてが無効になるため、キャッシュからは削除します。変更があったクエリのマップである
MERGE
テーブルを使用するクエリも削除の対象になります。INSERT
、UPDATE
、DELETE
、TRUNCATE
、ALTER
TABLE
、DROP TABLE
、DROP
DATABASE
など、様々なステートメントでテーブルは変化します。
InnoDB
テーブルを使用するトランザクションでもクエリ
キャッシュを使用します。
MySQL 5.1 では、ビューで生成したクエリもキャッシュします。
クエリ キャッシュは、SELECT
SQL_CALC_FOUND_ROWS ...
のクエリで動作し、後続する SELECT
FOUND_ROWS()
クエリで返る値を格納します。FOUND_ROWS()
は前のクエリがキャッシュからフェッチしていても、正確な値を返します。これは、検索したレコードの数をキャッシュで保管しているためです。SELECT
FOUND_ROWS()
クエリ自体はキャッシュの対象ではありません。
次のテーブルに示す関数を含む場合は、どのようなクエリでもキャッシュの対象にはなりません。
BENCHMARK() |
CONNECTION_ID() |
CURDATE() |
CURRENT_DATE() |
CURRENT_TIME() |
CURRENT_TIMESTAMP() |
CURTIME() |
DATABASE() |
ENCRYPT() (パラメータなし) |
FOUND_ROWS() |
GET_LOCK() |
LAST_INSERT_ID() |
LOAD_FILE() |
MASTER_POS_WAIT() |
NOW() |
RAND() |
RELEASE_LOCK() |
SYSDATE() |
UNIX_TIMESTAMP() (パラメータなし) |
USER() |
次の条件がある場合のクエリもキャッシュの対象にはなりません。
ユーザ定義関数 (UDF) または格納された関数 (stored functions) を指す場合
ユーザ変数を指す場合
mysql
システム
データベースのテーブルを指す場合
次に示す形のものである場合
SELECT ... IN SHARE MODE SELECT ... FOR UPDATE SELECT ... INTO OUTFILE ... SELECT ... INTO DUMPFILE ... SELECT * FROM ... WHERE autoincrement_col IS NULL
最後の例がキャッシュにならない理由は、それが ODBC のワークアラウンド (特別の手段) として、最後のインサート ID 値が存在するため。章 24. MySQL コネクタ の MyODBC セクションを参照のこと。
準備されたステートメントとして発行した場合。プレースホルダを採用していない場合も同様。例として、次のようなクエリはキャッシュにならない。
char *my_sql_stmt = "SELECT a, b FROM table_c"; /* ... */ mysql_stmt_prepare(stmt, my_sql_stmt, strlen(my_sql_stmt));
詳細は 項23.2.4. 「準備されたC APIステートメント。」 を参照してください。
TEMPORARY
テーブルを使用している場合
テーブルを全く使用しない場合。
関連テーブルのすべてに対して、ユーザがカラム レベルの権限を持つ場合。