MySQL-сервер содержит встроенный механизм кэширования запросов, который не включен по умолчанию. Кэширование запросов позволяет повысить производительность приложений, не погружаясь в структуру самих запросов.
После включения кэш работает автоматически. При каждом запросе типа SELECT
результат выполнения заносится в кэш, если результат не больше значения query_cache_limit
(с версии MySQL 8.0 параметр устарел).
Запросы типа UPDATE
, INSERT
, DELETE
, REPLACE
к таблице - удаляют весь кэш этой таблицы, созданный запросами SELECT
. Например, в таблицах, где при просмотре статьи обновляется счетчик количества просмотров, типа UPDATE table_name SET viewcount = viewcount+1 WHERE id=...
запросы SELECT
кэшироваться не будут. То есть запрос UPDATE
будет постоянно удалять весь кэш к таблице table_name
.
Кэширование запросов имеет следующие особенности:
SELECT * FROM ...
и select * FROM ...
(разный регистр инструкции SELECT
) будут для кэша двумя разными запросами.SELECT
к представлениям VIEW
.Запросы, которые вообще не подлежит кэшированию:
NOW()
, CURTIME()
, SLEEP()
, RAND()
, LAST_INSERT_ID()
и т.д.mysql
, INFORMATION_SCHEMA
или performance_schema
.SELECT ... FOR UPDATE
, SELECT ... IN SHARE MODE
, SELECT ... INTO OUTFILE
, SELECT ... INTO DUMPFILE
, SELECT * FROM ... WHERE autoincrement_col IS NULL
.Чтобы посмотреть параметры кэширования по умолчанию MySQL-сервера, воспользуемся терминалом:
mysql [(none)]> SHOW variables like 'query_cache%'; --- +------------------------------+---------+ --- | Variable_name | Value | --- +------------------------------+---------+ --- | query_cache_limit | 1048576 | --- | query_cache_min_res_unit | 4096 | --- | query_cache_size | 1048576 | --- | query_cache_strip_comments | OFF | --- | query_cache_type | OFF | --- | query_cache_wlock_invalidate | OFF | --- +------------------------------+---------+ --- 6 rows in set (0.001 sec)
Где параметры:
query_cache_size
- максимальный объем памяти (в байтах), выделяемый под кэширование запросов. Значение 0 - отключает механизм кэширования.query_cache_type
- определяет включено ли кэширование (1) или нет (0). При использовании (2) кэшироваться будут только запросы, в которых есть директива SQL_CACHE
(об этой директиве в конце);query_cache_wlock_invalidate
- определяет будут ли данные браться из кэша, если таблица, к которым они относятся заблокирована на чтение.query_cache_limit
- размер максимальной выборки (в байтах), который может быть помещен в кэш (с версии MySQL 8.0 параметр устарел и вычисляется автоматически на основе статистики запросов).Чтобы включить кэш запросов и выделить под него 10 мегабайт памяти можно выполнить запрос с правами суперпользователя:
mysql [(none)]> SET global query_cache_size=10*1024*1024; mysql [(none)]> SET global query_cache_limit=100*1024; mysql [(none)]> SET global query_cache_type=1
В момент начала записи MySQL не знает о размере выборки. Если записанный в кэш размер выборки больше, чем query_cache_limit
, то запись прекращается и занятое место освобождается. Следовательно, если вы знаете наперед, что результат выборки будет большим чем query_cache_limit
, то рекомендуется выполнять его с директивой SELECT SQL_NO_CACHE ... FROM ...
.
Для дефрагментации кэша можно выполнить команду FLUSH QUERY CACHE
. Эта инструкция переносит все запросы, хранящиеся в кэше в его начало и помечает оставшуюся память как один свободный блок).
После перезагрузки MySQL-сервера установленный параметры примут значение по умолчанию и кэширование прекратиться. Что бы включить кэширование на постоянной основе, необходимо добавить вышеуказанные параметры в файл конфигурации MySQL-сервера, в секцию [mysqld]:
[mysqld] query_cache_type = 1 query_cache_size = 10M query_cache_limit = 100К
Посмотреть состояние кэша можно с помощью запроса:
mysql [(none)]> SHOW GLOBAL STATUS LIKE 'Qcache%';
Будет выведена таблица с параметрами:
Qcache_free_blocks
- показывает сколько свободных блоков есть в кэше;Qcache_total_blocks
- количество занятых блоков;Qcache_free_memory
- сколько свободной памяти осталось в кэше;Qcache_hits
- количество запросов, результаты которых были взяты из кэша;Qcache_inserts
- количество запросов, которые были добавлены в кеш;Qcache_lowmem_prunes
- количество запросов, которые были удалены из кэша из-за нехватки памяти;Qcache_not_cached
- количество запросов, которые не были записаны в кеш из-за использования функций работы со временем и т.п.;Qcache_queries_in_cache
- количество запросов, которые находятся в кэше.Мерой эффективности кэша может служить отношение Qcache_hits / (Qcache_inserts + Qcache_not_cached)
.
Определить медленные запросы можно, по средствам включения логов медленных/тяжелых запросов (slow_log
).
После того как медленные запросы к БД MySQL определены и оптимизация этих запросов не помогает, то их можно принудительно закэшировать на стороне MySQL-сервера, применив дополнительную инструкцию SQL_CACHE
, например:
SELECT SQL_CACHE id, title, author FROM news WHERE date = `2023-05-09`;
Перед этим необходимо включить механизм кэширования MySQL-сервера в режим query_cache_type=2
или query_cache_type=1
. Режим query_cache_type=2
будет кэшировать запросы только с дополнительной инструкцией SQL_CACHE
.
Внимание! Запросы с принудительным кэшированием должны придерживаться правил, описанных в начале материала "Особенности работы кэша MySQL-сервера", что бы их кэш не аннулировался.