Database Journal
MS SQL Oracle DB2 Access MySQL PostgreSQL Sybase PHP SQL Etc SQL Scripts & Samples Links Database Forum

» Database Journal Home
» Database Articles
» Database Tutorials
MS SQL
Oracle
DB2
MS Access
MySQL
» RESOURCES
Database Tools
SQL Scripts & Samples
Links
» Database Forum
» Sitemap
Free Newsletters:
DatabaseDaily  
News Via RSS Feed


follow us on Twitter
Database Journal |DBA Support |SQLCourse |SQLCourse2
 

Featured Database Articles

MySQL

Posted Nov 18, 2003

MySQL's Query Cache - Page 2

By Ian Gilfillan

Clearing the Query cache

The cache cannot stay in memory indefinitely. Luckily, MySQL is clever enough to clear it when you make any changes to the tables used in a cache query. If we insert a new record to the cur table, MySQL will clear the affected queries (and only the affected queries) from the cache:

mysql> INSERT INTO cur(cur_user_text) 
    VALUES ('xxx');
Query OK, 1 row affected (0.06 sec)

mysql> SHOW STATUS LIKE '%qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_queries_in_cache | 0        |
| Qcache_inserts          | 4        |
| Qcache_hits             | 1        |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 2        |
| Qcache_free_memory      | 20962720 |
| Qcache_free_blocks      | 1        |
| Qcache_total_blocks     | 1        |
+-------------------------+----------+

Any of INSERT, UPDATE, DELETE, TRUNCATE, ALTER, DROP TABLE or DROP DATABASE potentially remove queries from the cache. You can manually clear the query cache with RESET QUERY CACHE.

Query Cache on demand

Earlier we saw there were three values for the query_cache_type. On, off and on demand. The latter option means that queries will only be cached if SQL_CACHE is specified in the query. Let's restart the server, with

query-cache-type = 2

in the configuration. Restarting the server flushes all the status variables. We run our previous query again:

SELECT cur_is_new FROM cur WHERE cur_user_text > 'Y'
...
2336 rows in set (0.27 sec)

It is back to a longer time again, as the cache has been flushed.

mysql> SHOW STATUS LIKE '%qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_queries_in_cache | 0        |
| Qcache_inserts          | 0        |
| Qcache_hits             | 0        |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 1        |
| Qcache_free_memory      | 20962720 |
| Qcache_free_blocks      | 1        |
| Qcache_total_blocks     | 1        |
+-------------------------+----------+

Nothing has been recorded. To store a query in the cache, we need to run the query with SQL_CACHE, as follows:

SELECT SQL_CACHE cur_is_new FROM cur WHERE cur_user_text > 'Y'
...
2336 rows in set (0.33 sec)

This time it has been stored in the cache.

mysql> SHOW STATUS LIKE '%qcache%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_queries_in_cache | 1        |
| Qcache_inserts          | 1        |
| Qcache_hits             | 0        |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 1        |
| Qcache_free_memory      | 20947592 |
| Qcache_free_blocks      | 1        |
| Qcache_total_blocks     | 4        |
+-------------------------+----------+

If the cache type is set to 1, there may be times when you know the query you are running will not be repeated, or more infrequently. In these situations, you can ask MySQL not to store the results in the cache, even if they adhere to the size limitations, with the SQL_NO_CACHE clause in the SELECT statement.

Block allocation and the Query cache

MySQL allocates results into the cache in blocks, during retrieval. This allocation comes at an overhead (see the quicker time to run the above query when it was not being cached). You should not enable the query cache unless you can make good use of it. The number of free blocks (Qcache_free_blocks) can be an indication of fragmentation - a high number in relation to the total number of the blocks means that space is being wasted. In MySQL 4.1, there is another cache-related variable: query_cache_min_res_unit. This allows you to set a minimum block size. The default is 4KB. If most of your query results are small, and you see fragmentation, you should decrease this. The converse applies if most of your result sets are large. To defragment a query cache, you can use FLUSH QUERY CACHE (FLUSH TABLES has the same effect on the cache).

There are situations when a query cannot be cached, all of which make perfect sense, such as when returning the current time, a random number, user variables, or when dumping to a file. Any queries making use of the following functions, or of the following types, will not be cached:

  • User-Defined Functions
  • BENCHMARK
  • CONNECTION_ID
  • CURDATE
  • CURRENT_DATE
  • CURRENT_TIME
  • CURRENT_TIMESTAMP
  • CURTIME
  • DATABASE
  • ENCRYPT (with one parameter)
  • FOUND_ROWS
  • GET_LOCK
  • LAST_INSERT_ID
  • LOAD_FILE
  • MASTER_POS_WAIT
  • NOW
  • RAND
  • RELEASE_LOCK
  • SYSDATE
  • UNIX_TIMESTAMP (without parameters)
  • USER
  • query contains user variables
  • query references the mysql system database
  • query of the form SELECT ... IN SHARE MODE
  • query of the form SELECT ... INTO OUTFILE ...
  • query of the form SELECT ... INTO DUMPFILE ...
  • query of the form SELECT * FROM AUTOINCREMENT_FIELD IS NULL
  • queries inside transactions (in MySQL 4.0.x)

Wisely used, the query cache can make a substantial difference to struggling applications. Good luck!

» See All Articles by Columnist Ian Gilfillan



MySQL Archives

Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 




Latest Forum Threads
MySQL Forum
Topic By Replies Updated
MySQL in high availability and transction secure banking application klamor 1 August 28th, 10:24 AM
MySQL rollback UAL225 1 August 28th, 10:15 AM
Browsing a DB file that uses MySql finleytech 1 July 26th, 10:51 AM
php cookie won't pass variable to next page ITdevGirl 0 June 22nd, 12:13 PM