Как кэшировать / оптимизировать результат запроса MySQL в Wordpress, не создавая еще большей нагрузки?
Привет.
Есть виджет WP популярных игр за сутки / неделю / месяц / все время. Да к тому же с навигацией на 10 страниц. Он ежедневно генерирует большое количество тяжелых запросов - на каждой загрузке страниц, каждом переключении его вкладок, каждой навигации по этим записям.
Первое, что приходит в голову - кэшировать данные о просмотрах. То есть поставить на крон, и раз в 3-6 часов проходится по всем записям, пересчитывать динамику и запихивать в произвольные поля, по которым уже сортировать записи. Но штука в том, что так запросов станет еще больше, причем в несколько раз. Единственное, что так можно добиться - ускорить работу самого виджета ценой еще большей нагрузки на систему.
Есть ли способ кэширования таким образом, чтобы не создавалась еще большая нагрузка? Либо другие способы оптимизации? Или вообще другие способы решения задачи? Просто удалить не вариант... Как с этим борются другие проекты, у которых похожий функционал?
P.S. Занялся проблемой, потому что на reg.ru, где я сайт этот держу, превысил лимит процессорного времени. А у меня всего-то там 1300 хостов. Пришлось тариф повышать. Что будет, когда станет 5-10к?
Стоит начать с этих вопросов:
А зачем этой задаче нужен реалтайм и точность до 1го поста?
Если будут данные ошибочны, пользователи убегут?
Зачем показывать им именно эти посты, может лучше будет показать что-то другое, где, например, выше конверсия?
Сколько пользователей просматривает все 10 страниц этой выдачи?
Ну и, если все, что выше почему-то имеет смысл именно в такой реализации, стоит подумать над этим вопросом:
Почему этот запрос выполняется при каждой загрузке страниц/переключении вкладок?
Дмитрий,
А зачем этой задаче нужен реалтайм и точность до 1го поста?
Если будут данные ошибочны, пользователи убегут?
// Потому что если я это кэширую, заспросов в сутки станет только больше. Об этом и тема, собсно
Зачем показывать им именно эти посты, может лучше будет показать что-то другое, где, например, выше конверсия?
// Такой функционал. Сайт игровой тематики. Надо выводить популярные игры.
Сколько пользователей просматривает все 10 страниц этой выдачи?
// Если страница / вкладка не просматривается, лишнее не подгружается. Там ajax-подгрузка по типу "вперед / назад". То есть выводится топ-50 игр, разделенных на 10 страниц по 5 штук.
Ну и, если все, что выше почему-то имеет смысл именно в такой реализации, стоит подумать над этим вопросом:
Почему этот запрос выполняется при каждой загрузке страниц/переключении вкладок?
// Вкладок виджета - не браузера. А страниц - потому что он в сайдбаре. Как он может не выполнятся каждый раз? Не, можно наверно разок выполнить и заткнуть результат в переменные сессии или тип того. Но это особого смысла не имеет. У меня глубина просмотра не такая большая, чтобы получить существенный выигрыш производительности от этого...
допустим, нужно вывести самые популярные за час - проверяем, есть ли такое значение в трансиент кэше, если нет, делаем тяжелый запрос запрос, отдаем и кладем его в кэш, говорим, что он будет валиден час, держим его там час
Есть ли способ кэширования таким образом, чтобы не создавалась еще большая нагрузка?
Собственно кэширование есть способ сэкономить на медленных запросах. Как я понимаю в вопросах работы алгоритмов вы не в зуб ногой, больше по настройке формочек в вордпрессе... Кэш создается 1 раз, и используется для всех дальнейших запросов как готовый ответ от бд, на определенный срок. Для этого во многих инструментах кэширования есть штатные методы отслеживания интервала хранения конкретного значения.
Условно: выбираете топ 10 количества просмотров игр, кладете в кэш на час, и пока кэш существует в базу не лезете, тащите из кэша. Как только кэш автоматически очищается - делаете еще раз запрос, опять кладете в кэш... Таким образом вместо 500 запросов в час у вас будет 1 запрос, все остальное будет тащиться из кэша, и данные будут не старше часа по актуальности. Можете сократить / увеличить время кеширования и таким образом балансировать в плане нагрузка/актуальность данных.
Не надо так жестко... Просто никогда не сталкивался с необходимостью что-то кэшировать. Тем более на вордпрессе.
Я вроде бы понял посыл. Надо кэшировать не отдельные цифреки, как я хотел, а сразу весь результат запроса. Тогда смысл в этом действительно есть. Окей.
Но где его хранить? Как это грамотно делается? В таблицу отдельную в бд засунуть что ли?
ThunderCat, а почему нет? Ну да, он типа плохо оптимизирован сам по себе.. Зато удобно. Да и "более-менее" серьезное - это, на мой взгляд, от 50 до 100к трафика в сутки.. В моем случае до этого далековато.
Ээээ... Если просто положить цифры посчитанные кроном в memcache\redis\mysql\file - уже будет проще. Я не пойму, с чего вы решили, что запросов станет больше?
Ну смотрите. Допустим я показываю вот эти 5 игр. Каждый просмотр страницы - это минимум 1 запрос. То есть 2000 хитов = минимум 2000 запросов. На практике гораздо больше, потому что кто-то поклацает навигацию, кто-то вкладки и короче где-то 5-10к выйдет за сутки.
Чтобы кэшировать результат запроса, нужно раз в 3-6 часов пройтись кроном по ВСЕМ играм в базе и пересчитать им просмотры: за сутки, за неделю, за месяц, за все время + куда-то это записать, чтобы по этому значению сортировать потом. Допустим, у меня будет 1000 игр на сайте (сейчас порядка 100 всего лишь). 1000 * 4 вкладки * 4 (то есть раз в 6 часов) - 16к запросов в сутки + облегченные запросы из виджета.