Стоит ли когда-нибудь издержек частой аннулирования кэша запросов?

22

В настоящее время я работаю с базой данных MySQL, где мы видим большое количество недействительных данных в кеше запросов, в основном из-за большого количества операторов INSERT, DELETE и UPDATE, которые выполняются во многих таблицах.

Я пытаюсь определить, есть ли какая-либо польза от использования кэша запросов для операторов SELECT, которые выполняются с этими таблицами. Поскольку они так быстро становятся недействительными, мне кажется, что лучше всего было бы просто использовать SQL_NO_CACHE в инструкциях SELECT с этими таблицами.

Стоит ли когда-нибудь накладных расходов на частую инвалидность?

Изменить: По запросу пользователя @RolandoMySQLDBA ниже, здесь информация о MyISAM и INNODB.

InnoDB

  • Размер данных: 177,414 ГБ
  • Размер индекса: 114,792 ГБ
  • Размер таблицы: 292,205 ГБ

MyISAM

  • Размер данных: 379,762 ГБ
  • Размер индекса: 80,681 ГБ
  • Размер таблицы: 460,443 ГБ

Дополнительная информация:

  • Версия: 5.0.85
  • query_cache_limit: 1048576
  • query_cache_min_res_unit: 4096
  • query_cache_size: 104857600
  • query_cache_type: ON
  • query_cache_wlock_invalidate: OFF
  • innodb_buffer_pool_size: 8841592832
  • 24 ГБ ОЗУ
Крейг Сефтон
источник
2
dom.as/tech/query-cache-tuner резюмирует это довольно хорошо
Laurynas Biveinis
Хе-хе, очень проницательный.
Крейг Сефтон

Ответы:

16

Вы должны просто отключить кеш запросов с помощью

[mysqld]
query_cache_size = 0

и затем перезапустите MySQL. Зачем мне это предлагать ???

Кэш запросов всегда будет бодаться с InnoDB. Было бы хорошо, если бы MVCC InnoDB позволял обрабатывать запросы из кеша запросов, если изменения не влияют на повторяющиеся операции чтения для других транзакций. К сожалению, InnoDB просто не делает этого. Очевидно, у вас есть много запросов, которые довольно быстро становятся недействительными и, вероятно, не используются повторно.

Для InnoDB под MySQL 4.0 кеш запросов был отключен для транзакций. Для MySQL 4.1+ InnoDB проигрывает данные трафика, когда разрешает доступ к кешу запросов для каждой таблицы.

С точки зрения вашего вопроса, я бы сказал, что оправдание удаления кэша запросов - это не столько накладные расходы, сколько то, как InnoDB управляет этим.

Для получения дополнительной информации о том, как InnoDB взаимодействует с кешем запросов, пожалуйста, прочитайте страницы 213-215 книги «Высокопроизводительный MySQL (второе издание)» .

Если все или большинство ваших данных являются MyISAM, вы можете использовать свою исходную идею использования SQL_NO_CACHE.

Если у вас есть сочетание InnoDB и MyISAM, вам нужно будет найти правильный баланс для вашего приложения в зависимости от того, насколько высоки ваши потери в кеше. На самом деле, страницы 209-210 этой же книги указывают на причины пропуска кэша:

  • Запрос не может быть кэширован либо потому, что он содержит недетерминированную конструкцию (например, CURRENT_DATE), либо потому, что его набор результатов слишком велик для хранения. Оба типа не кэшируемых запросов увеличивают переменную состояния Qcache_not_cached.
  • Сервер никогда не видел запрос раньше, поэтому у него никогда не было возможности кэшировать его результат.
  • Результат запроса ранее был кэширован, но сервер удалил его. Это может произойти из-за недостатка памяти для хранения, из-за того, что кто-то дал команду серверу удалить его, или потому что он был признан недействительным.

и основными причинами большого количества кеш-пропусков с небольшим количеством некэшируемых запросов могут быть:

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

ОБНОВЛЕНИЕ 2012-09-06 10:10 ПО ВОСТОЧНОМУ ВРЕМЕНИ

Просматривая вашу последнюю обновленную информацию, вы query_cache_limitустановили 1048576 (1M). Это ограничивает любой результат до 1M. Если вы получите что-то большее, оно просто не будет кэшировано. Хотя вы query_cache_sizeустановили значение 104857600 (100M), это позволяет использовать только 100 кэшированных результатов в идеальном мире. Если вы выполните сотни запросов, фрагментация произойдет довольно быстро. У вас также есть 4096 (4K) в качестве минимального набора результатов. К сожалению, в mysql нет внутреннего механизма дефрагментации кеша запросов.

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

SET GLOBAL query_cache_size = 0;
SELECT SLEEP(60);
SET GLOBAL query_cache_size = 1024 * 1024 * 1024;

для того, чтобы очистить кеш запросов. Вы теряете все кэшированные результаты, поэтому запускайте эти строки в непиковые часы.

Я бы также назначил следующее:

  • query_cache_size = 1G
  • query_cache_limit = 8M

Это оставляет 23 ГБ ОЗУ. Я хотел бы поднять следующее:

  • innodb_buffer_pool_size = 12G
  • key_buffer_size = 4G

Это оставляет 7G. Это должно быть достаточно для соединений с ОС и БД.

Помните, что буфер ключей кэширует только страницы индекса MyISAM, а пул буферов InnoDB кэширует данные и индексы.

Еще одна рекомендация: обновите MySQL до 5.5, чтобы можно было настроить InnoDB для нескольких процессоров и нескольких потоков для операций ввода-вывода с возможностью чтения / записи.

Смотрите мои предыдущие посты об использовании MySQL 5.5 в сочетании с доступом к нескольким процессорам для InnoDB

ОБНОВЛЕНИЕ 2012-09-06 14:56 ПО ВОСТОЧНОМУ ВРЕМЕНИ

Мой метод очистки кэша запросов довольно экстремальный, потому что он хранит кэшированные данные и образует совершенно другой сегмент оперативной памяти. Как вы указали в своем комментарии, FLUSH QUERY CACHE(как вы предложили) или даже RESET QUERY CACHEбудет лучше. Для пояснения, когда я сказал «нет внутреннего механизма», я имел в виду именно это. Дефрагментация необходима и должна быть сделана вручную. Это должно быть crontab'd .

Если вы выполняете DML (INSERT, UPDATEs, DELETEs) на InnoDB чаще, чем на MyISAM, я бы сказал, что нужно вообще удалить кеш запросов, о чем я говорил в начале.

RolandoMySQLDBA
источник
Спасибо за ответ. У меня есть эта книга, и я широко ее использую; Я хорошо знаю причины, которые вы наметили для ошибок кэша, но, как я уже говорил, мы уже определили недействительность кэша как ключевую проблему из-за сильной корреляции, которую мы наблюдаем между Com_select и Qcache_inserts. О, и у рассматриваемой БД есть смесь INNODB и MyISAM.
Крейг Сефтон,
Обновлено с дополнительной информацией, которую вы запросили. Спасибо.
Крейг Сефтон
Спасибо за ответ, с нетерпением жду остальных. Одна из вещей, которые мы определили, заключалась в том, что около 18% запросов не кэшировались, поэтому определенно благодарны за совет относительно настроек. К сожалению, коробка не предназначена, но ваши рекомендации должны помочь. Фрагментация, безусловно, также является проблемой. Я по-прежнему очень обеспокоен количеством недействительных данных, которые мы видим (в отличие от запросов, которые вообще не кэшируются), поэтому все еще не уверен, стоит ли накладные расходы там. Действительно ценю вашу проницательность, большое спасибо.
Крейг Сефтон
Что касается вашего комментария о том, что «mysql не имеет внутреннего механизма для дефрагментации кеша запросов», не могли бы вы выполнить команду FLUSH QUERY CACHEдля его дефрагментации? См. Dev.mysql.com/doc/refman/5.0/ru/flush.html
Крейг Сефтон,
Обновил
3

BAD: query_cache_size = 1G

Зачем? Из-за того, сколько времени займет флеш. То есть, когда происходит некоторая запись, весь 1 ГБ будет сканироваться, чтобы найти любые ссылки на таблицу, которая была изменена. Чем больше КК, тем медленнее это. Я рекомендую размер не более 50M, если ваши данные редко меняются.

КК накладные расходы для MyISAM и InnoDB. Он выводит глобальный Mutex и выводит его слишком рано. Этот мьютекс является одной из причин того, что MySQL не может эффективно использовать более 8 ядер.

SQL_NO_CACHE не не заметил , пока после того, как мьютекс заблокирован! О единственном использовании этого флага для тестирования.

Зачастую лучше отдать ОЗУ в какой-то другой кеш.

Рик Джеймс
источник
2

Я могу придумать идеальный вариант для этого, и мы тщательно протестировали и запустили его в производство ... Я называю это стратегией кластеризации "fast lane" :

Если вы выполняете разделение на чтение и запись с помощью прокси-сервера, такого как MaxScale, или ваше приложение способно, вы можете отправить некоторые операции чтения для этих редко аннулированных таблиц только ведомым, у которых включен кэш запросов, а остальные - другим ведомым с ним. выключено.

Мы делаем это и, в результате, обрабатываем 4M вызовов в минуту в кластере во время наших нагрузочных тестов (а не тестов ... реальной сделки). Приложение ожидает некоторых функций master_pos_wait (), поэтому оно ограничено потоком репликации, и хотя мы видели его с состоянием ожидания аннулирования Qcache с очень высокой пропускной способностью, эти уровни пропускной способности выше, чем у кластера. способен без Qcache.

Это работает, потому что в крошечном кеше запросов на этих машинах редко можно найти что-либо недействительное (эти запросы относятся только к редко обновляемым таблицам). Эти коробки - наша «быстрая полоса». Что касается остальных запросов, выполняемых приложением, им не нужно бороться с Qcache, поскольку они переходят в блоки без его включения.

Кристофер Макгоуэн
источник