Кэш запросов

Кэш запросов хранит сжатые наборы результатов в памяти и повторно использует их для последующих запросов, когда это возможно. Вы можете настроить его с помощью следующих директив:

  • qcache_max_bytes — ограничение на использование ОЗУ для хранения кэшированных запросов. По умолчанию 16 МБ. Установка qcache_max_bytes в 0 полностью отключает кэш запросов.
  • qcache_thresh_msec — минимальное время выполнения запроса (в миллисекундах) для кэширования. Запросы, которые выполняются быстрее этого времени, не будут кэшироваться. По умолчанию 3000 мс, или 3 секунды.
  • qcache_ttl_sec — время жизни кэшированной записи. Запросы будут храниться в кэше в течение этого времени. По умолчанию 60 секунд, или 1 минута.

Эти настройки можно изменять на лету с помощью оператора SET GLOBAL:

mysql> SET GLOBAL qcache_max_bytes=128000000;

Эти изменения применяются немедленно, и кэшированные наборы результатов, которые больше не соответствуют ограничениям, сразу же удаляются. При уменьшении размера кэша на лету выигрывают наиболее недавно использованные (MRU) наборы результатов.

Кэш запросов работает следующим образом. Когда он включен, каждый результат полнотекстового поиска полностью сохраняется в памяти. Это происходит после полнотекстового сопоставления, фильтрации и ранжирования, то есть по сути мы сохраняем пары {docid,weight} для total_found. Сжатые совпадения могут занимать в среднем от 2 до 12 байт на совпадение, в основном в зависимости от дельт между последовательными docid. После завершения запроса мы проверяем пороги времени выполнения и размера, и либо сохраняем сжатый набор результатов для повторного использования, либо отбрасываем его.

Обратите внимание, что влияние кэша запросов на ОЗУ не ограничивается qcache_max_bytes! Если, например, выполняется 10 параллельных запросов, каждый из которых совпадает с до 1 млн совпадений (после фильтров), то пиковое временное использование ОЗУ будет в диапазоне от 40 МБ до 240 МБ, даже если запросы достаточно быстрые и не кэшируются.

Запросы могут использовать кэш, когда совпадают таблица, полнотекстовый запрос (то есть содержимое MATCH()) и ранжировщик, а фильтры совместимы. Это означает:

  • Полнотекстовая часть внутри MATCH() должна совпадать посимвольно. Добавьте один дополнительный пробел — и для кэша запросов это уже другой запрос.
  • Ранжировщик (и его параметры, если есть, для пользовательских ранжировщиков) должен совпадать посимвольно.
  • Фильтры должны быть надмножеством исходных фильтров. Вы можете добавить дополнительные фильтры и всё равно попасть в кэш. (В этом случае дополнительные фильтры будут применены к кэшированному результату.) Но если вы уберёте какой-то фильтр, это будет уже новый запрос.

Записи кэша истекают по TTL и также инвалидируются при ротации таблицы, или при выполнении TRUNCATE, или ATTACH. Обратите внимание, что в настоящее время записи не инвалидируются при произвольных записях в RT-таблицы! Поэтому кэшированный запрос может возвращать устаревшие результаты в течение времени жизни TTL.

Вы можете просмотреть текущий статус кэша с помощью SHOW STATUS через переменные qcache_XXX:

mysql> SHOW STATUS LIKE 'qcache%';
+-----------------------+----------+
| Counter               | Value    |
+-----------------------+----------+
| qcache_max_bytes      | 16777216 |
| qcache_thresh_msec    | 3000     |
| qcache_ttl_sec        | 60       |
| qcache_cached_queries | 0        |
| qcache_used_bytes     | 0        |
| qcache_hits           | 0        |
+-----------------------+----------+
6 rows in set (0.00 sec)
Last modified: August 28, 2025