code prettify

Sunday 23 August 2015

Importance of MySQL cache

My test environment is:
Ubuntu 14.04 Trusty Tahr
MySQL Server version: 5.5.44-0ubuntu0.14.04.1 (Ubuntu)

MySQL uses sql cache to store results of queries that have been executed so that when the same query is executed again it retrieves the result data set from the cache instead of getting it again from db. So it is faster data access.

It is by default enabled in MySQL.

This is interesting since there is one question we ought to ask here whether we should use it or disable it or just leave it as it is who cares :).

Ok, moving forward today's session goals are:
  1.     How useful is MySQL cache?
  2.     When to use it and when not to use it?
  3.     What to do if you do not want to use it?

There are some catchy areas here too like not all your queries will be stored in cache. For example, a query executed inside a stored function will not be stored in cache. Below doc link from MySQL further details out the specifics.

https://dev.mysql.com/doc/refman/5.5/en/query-cache-operation.html

Starting with our goals:

1. How useful is MySQL cache?

It is very useful indeed as once you have the result data set, if the same query is executed again, the data is now fetched from the cache and it is much faster.

2. When to use it and when not to use it?


As per MySQL doc "If a table changes, all cached queries that use the table become invalid and are removed from the cache." https://dev.mysql.com/doc/refman/5.5/en/query-cache-operation.html .

So if you have executed a query and any content in any of the tables used in the query has changed (whether related or not to the dataset for the query), all the cache entries using those tables will be flushed and executing the same query again will fetch the data from the database.

So is this bad or is fine? Depends :).

If the query you are executing is very often executed lets say 5-6 times every minute and the related tables in database are altered very often lets say at a similar rate 5-6 times a second, so we even if all the queries are stored in cache but are ultimately flushed when related table data is changed, leading to fetching once again from database and storing in cache, but which we are never able to utilize.

So in this case if the table data is too often changed then it is better not to use cache for related queries since using cache adds a certain overhead (13% as stated below) to MySQL.

https://dev.mysql.com/doc/refman/5.5/en/query-cache.html

"If all the queries you are performing are simple (such as selecting a row from a table with one row), but still differ so that the queries cannot be cached, the overhead for having the query cache active is 13%. This could be regarded as the worst case scenario. In real life, queries tend to be much more complicated, so the overhead normally is significantly lower."

Otherwise if the table is less fairly changed and the query fetching the data is more frequent then it is more efficient to use cache.

3. What to do if you do not want to use it?


As discussed above, if you do not want to use it for a query which is not able to benefit the cache storage use SQL_NO_CACHE option while executing the query
which tells MySQL not to store the result set in cache.

Eg. SELECT SQL_NO_CACHE id, name FROM customer;

https://dev.mysql.com/doc/refman/5.5/en/query-cache-in-select.html

3 comments:

  1. Your details are correct, but I disagree with your conclusions. I say "turn off the QC". In a typical production environment, there are enough writes happening to cause frequent pruning, and rarely finding a "hit". Pruning costs something, especially if query_cache_size is more than, say, 50M. So, even if you choose to have it ON (or DEMAND), keep the size down.

    Some metrics:
    Qcache_not_cached / (Qcache_hits + Com_select + Qcache_not_cached) -- % of selects not cached. (want low)
    Qcache_hits / Qcache_inserts -- Hit to insert ratio (want low)
    Qcache_hits / (Qcache_hits + Com_select) -- Hit ration (want high)

    ReplyDelete
    Replies
    1. Thanks Richard for your valuable input and the metrics to monitor while using it to check query cache overall usage.

      Delete