Запрос кэшируется при локальной настройке, но никогда на сервере?
У меня много проблем с кэшем запросов в проекте: я использую версию MySQL, написанную на Percona, с теми же версиями, что и на моей локальной машине разработки, и на рабочем сервере. Теперь, включение кэша запросов дает мне отличные результаты на моем локальном компьютере: практически все запросы, которые должны быть кэшированы, эффективно.
Теперь точно такие же запросы не кэшируются на рабочем сервере. Все точно так же; переменные mysql, содержимое базы данных, кодовая база, вошедший в систему пользователь,... но при работе кэшируются только несколько запросов, все самые важные из них пропускаются. И я не могу понять, почему:-)
Итак, в поисках решения я работаю со следующим запросом, который используется для выбора трех последних тем из таблицы тем: (это самый "тяжелый" запрос, который я определенно хочу кэшировать!)
SELECT `topic`.* FROM `topics` AS `topic`
LEFT OUTER JOIN `topics` AS `topic_helper`
ON (`topic`.`id` = `topic_helper`.`id`
AND `topic_helper`.`created_on` < `topic`.`created_on`)
GROUP BY `topic`.`id` HAVING COUNT(*) < 3
ORDER BY `topic`.`created_on` DESC;
Итак, для начала, SHOW VARIABLES LIKE '%query_cache%
дать мне те же результаты, как локальные, так и на производстве:
+------------------------------+----------+
| Variable_name | Value |
+------------------------------+----------+
| have_query_cache | YES |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 10485760 |
| query_cache_strip_comments | OFF |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
+------------------------------+----------+
Выполнение вышеуказанного запроса кэшируется локально после первого запуска, так как SHOW PROFILE
ясно говорит мне в конце своего следа:
| Waiting for query cache lock | 0.000001 |
| Waiting on query cache mutex | 0.000001 |
| freeing items | 0.000000 |
| storing result in query cache | 0.000002 |
| logging slow query | 0.000001 |
| cleaning up | 0.000006 |
+--------------------------------+----------+
Второй вызов возвращает запрос из кэша, как и ожидалось.
На рабочем сервере выполнение этого запроса никогда не сохранит его в кеше. Набор результатов точно такой же, и явно не используются операторы, которые бы сделали недействительным кэширование запросов (согласно руководству на http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html - я уверен, что приведенный выше запрос соответствует требованиям для его кэширования.)
Для полноты, полный вывод SHOW PROFILE
для того же запроса на производственном сервере, вставлен здесь: http://pastebin.com/7Jm5rmVd
Кроме того, стоит отметить, что хотя конфигурация на обоих серверах абсолютно одинакова, моя локальная версия - 5.5.27, немного новее, чем в версии 5.5.17-55. Может ли быть, что это проблема..?
Я сравнил полный SHOW VARIABLES;
вывод с моего локального сервера в качестве рабочего сервера, чтобы увидеть, если что-то не хватает, но ничто не отличается, кроме системного часового пояса и пути к файлам журнала и т. д..
Итак, может кто-нибудь из вас знает, где искать дальше? Или есть какие-либо подсказки, что может быть причиной этого?
1 ответ
Здесь мы часто используем сервер Percona и сообщество MySQL.
Кэши запросов являются мощными и чрезвычайно сложными. Худшее, что может сделать MySQL, - это вернуть некоторые устаревшие данные кэша.
MySQL не только кэширует запросы, но и данные базы данных - и использует индексы для дополнительной производительности.
Все, что может сделать недействительным кеш запроса, делает его недействительным.
Как правило, мы не слишком фокусируемся на том, кэшируется он или нет... мы верим, что MySQL действует разумно - если по какой-то причине он считает, что что-то не должно кэшироваться, он не кэширует его. Хотя мы делаем то, что наши запросы максимально эффективны и просты.
Если я могу сказать это - я думаю, что вы столкнетесь с серьезными проблемами масштабируемости независимо от кеша запросов, если ваш пример запроса "один из наиболее используемых". Он будет работать как собака без ног, как только этот сервер будет занят!
В соответствии с вашей записью о вставке - создается хотя бы одна временная таблица, вероятно, из-за внешнего соединения (или GROUP BY).
Я все за нормализацию - но иногда производительность требует альтернативного маршрута.
Разве вы не можете кэшировать некоторые из этих данных самостоятельно, в какой-то таблице поиска / сводки? Триггеры могут быть вашими друзьями здесь:)