Table of Contents
From version 4.0.1, MySQL server features a Query Cache. When in use, the query cache stores the text of a SELECT query together with the corresponding result that was sent to the client. If an identical query is later received, the server will retrieve the results from the query cache rather than parsing and executing the same query again.
NOTE: The query cache does not return stale data. When data is modified, any relevant entries in the query cache are flushed.
The query cache is extremely useful in an environment where (some) tables don't change very often and you have a lot of identical queries. This is a typical situation for many web servers that use a lot of dynamic content.
Below is some performance data for the query cache. (These results were generated by running the MySQL benchmark suite on a Linux Alpha 2 x 500 MHz with 2 GB RAM and a 64 MB query cache):
If all of the queries you're performing are simple (such as selecting a row from a table with one row); but still differ so that the queries can not be cached, the overhead for having the query cache active is 13%. This could be regarded as the worst case scenario. However, in real life, queries are much more complicated than our simple example so the overhead is normally significantly lower.
Searches after one row in a one row table is 238% faster. This can be regarded as close to the minimum speedup to be expected for a query that is cached.
If you want to disable the query cache code set query_cache_size=0. By disabling the query cache code there is no noticeable overhead. (query cache can be excluded from code with help of configure option --without-query-cache)
Queries are compared before parsing, thus
SELECT * FROM tbl_name
and
Select * from tbl_name
are regarded as different queries for query cache, so queries need to be exactly the same (byte for byte) to be seen as identical. In addition, a query may be seen as different if for instance one client is using a new communication protocol format or another character set than another client.
Queries that uses different databases, uses different protocol versions or the uses different default character sets are considered different queries and cached separately.
The cache does work for SELECT SQL_CALC_FOUND_ROWS ... and SELECT FOUND_ROWS() ... type queries because the number of found rows is also stored in the cache.
If query result was returned from query cache then status variable Com_select will not be increased, but Qcache_hits will be. See Query Cache Status and Maintenance.
If a table changes (INSERT, UPDATE, DELETE, TRUNCATE, ALTER or DROP TABLE|DATABASE), then all cached queries that used this table (possibly through a MRG_MyISAM table!) become invalid and are removed from the cache.
Transactional InnoDB tables that have been changed will be invalidated when a COMMIT is performed.
In MySQL 4.0, the query cache is disabled inside of transactions (it does not return results). Beginning with MySQL 4.1.1, the query cache will also work inside of transactions when using InnoDB tables (it will use the table version number to detect if the data is still current or not).
Before MySQL 5.0, a query that begins with a leading comment might be cached, but could not be fetched from the cache. This problem is fixed in MySQL 5.0.
A query cannot be cached if it contains one of the functions:
Function | Function | Function |
User-Defined Functions | CONNECTION_ID | FOUND_ROWS |
GET_LOCK | RELEASE_LOCK | LOAD_FILE |
MASTER_POS_WAIT | NOW | SYSDATE |
CURRENT_TIMESTAMP | CURDATE | CURRENT_DATE |
CURTIME | CURRENT_TIME | DATABASE |
ENCRYPT (with one parameter) | LAST_INSERT_ID | RAND |
UNIX_TIMESTAMP (without parameters) | USER | BENCHMARK |
Nor can a query be cached if it contains user variables, references the mysql system database, is of the form SELECT ... IN SHARE MODE, SELECT ... INTO OUTFILE ..., SELECT ... INTO DUMPFILE ... or of the form SELECT * FROM AUTOINCREMENT_FIELD IS NULL (to retrieve last insert ID - ODBC work around).
However, FOUND_ROWS() will return the correct value, even if the preceding query was fetched from the cache.
In case a query does not use any tables, or uses temporary tables, or if the user has a column privilege for any of the involved tables, that query will not be cached.
Before a query is fetched from the query cache, MySQL will check that the user has SELECT privilege to all the involved databases and tables. If this is not the case, the cached result will not be used.