Как снизить количество динамических запросов AJAX?
Добрый день. Делаю сайт на PHP, MySQL + AJAX
На данный момент на главной странице выведен график (набор точек {X:Y}), который обновляется каждые 10 секунд с помощью AJAX. AJAX вызывает функцию на PHP, которая ищет в базе данных все значения для текущего графика и возвращает json ответ. По базе идет поиск по колонке ID графика и дате (последние 24 часа). Возвращает массив ID точки и X,Y точки. Каждый раз все точки загружаются полностью, то есть от самой первой до последней в течении текущих суток.
Работаю всего пару дней, посетителей даже нет. Но от одного меня нагрузка уже появилась на хостинг. Подскажите, в каком направлении двигаться, чтобы оптимизировать мои процессы? Если я один пользователь полностью съедаю все вычислительные мощности моего хостинг пакета за 200р, то страшно представить, что будет после запуска контекстной рекламы.
Использую хостинг на котором есть статистика нагрузки:
Зеленая область — запросы к статическим файлам, на обслуживание которых ресурсов практически не требуется.
Желтая область — запросы к скриптам вашего сайта, для выполнения которых выделяются ресурсы сервера.
У меня практически все запросы к сайту - желтые. Из тысячи запросов только 50 статические. При этом сайтом пока пользуюсь я сам.
1) таскать всю базу каждые 10 секунд - бред. По получению данных запомните время (а лучше передавайте его с сервера как отдельное поле) и в следующий раз передавайте ее на сервер в аякс запросе, исходя из нее уже вытаскивайте новые записи из бд, присоединяя их на клиенте к уже полученному ранее массиву данных.
2) Индексы на таблицы - посмотрите сколько отрабатывает типичный запрос, курите explain если медленно отрабатывает, добавляйте индексы на группы запрашиваемых полей.
3) кэширование с 10 секундным временем жизни самое то, если запрашиваете раз в 10 секунд, теоретически это снимет нагрузку на бд до уровня "как 1 пользователь" (при условии что данные не персонализированы, а общие для всех).
3. Я так понимаю, что при запросе, я могу кидать в кеш все значения за сегодня первому пользователю и потом другим пользователям выдавать кеш, так? В таком случае, есть ли какие-то рекомендации, где можно ознакомиться с кешированием, желательно под конкретную задачу, без полного изучения с нуля.
Плохой вариант, если запрос будет выполняться по 5 секунд(да даже по 1) это плохо, типичный запрос к таблице на 1 000 000 записей с индексами должен отрабатывать в пределах 0,5 секунды в пике, конечно учитывая нормальное железо и верно типизированные данные. Кэш не спасет если запрос будет ложить сервер.
где можно ознакомиться с кешированием, желательно под конкретную задачу, без полного изучения с нуля.
Задачи кеширования и инвалидации кеша в ощем случае относятся к сложным, с нуля все же сложно порекомендовать что-либо, но в вашем случае думаю простого кеша в файл/мемкеш будет достаточно, просто писать файл/создавать ключ как таймстамп, перед запросом проверять есть ли кеш с именем меньше чем $(текущее время - 10 секунд), если нет - почистить папку/мемкеш от всего, сделать запрос и создать новый файл/мемкеш ключ с результатами запроса.
joookleol, это ни о чем не говорит, замерять, конечно, нужно конкретно по количеству времени на скрипт/запрос к бд. Ну и все это у вас на самом дешевом тарифе, я так понимаю, так что это просто гадание на прошлогодней листве. Хотите оптимизацию - експлейн в руки и гоняйте запросы. И проверьте - может у вас в коде где затык... А то так у вас отрабатывает примерно за 0,3 секунды, запросы раз в 10 секунд -> одновременно на сайте могут находиться порядка 30 пользователей, дальше сервер ляжет/будет тупить.
— Доктор, когда я делаю вот так у меня болит.
— А вы так не делайте.
Для ответа по существу надо смотреть подробно что именно вы там наворотили, выяснить зачем вы обновляете этот график, почему целиком, и вообще в нем ли проблема, или в чем-то другом.
График представляет собой определенную статистику, которая должна быть постоянно актуальной.
почему целиком
А как я могу не целиком обновлять график? У меня каждые 10-15 секунд в базе появляется новое значение. И есть ли разница получить 1 строку из базы данных или, предположим, 5, если запрос в БД все-равно будет?
joookleol, да, разница между 1 и 5 есть.
А если новое значение появляется каждые 15 секунд, то это 5760, а не 1 и не 5.
Хинт: можно вытаскивать не все данные, а только свежие.
Хинт2: можно закешировать эти свежие данные в памяти, и не дергать базу.
joookleol, я предпочел бы редис или memcache, но если на хостинге их нет, то можно попытаться поднять процесс-демон(1, 2) и/или записать данные в shared memory, например. В зависимости от того, что у вас на хостинге есть. Накрайняк можно в файлик писать, это тоже будет быстрее чем БД в подавляющем большинстве случаев. На самом деле, небольшой файлик может выигрывать даже у редиса, если редис физически на другой машине, а файлик не выпадает из кеша ОС.
Если есть возможность запустить на хостинге профайлер, типа xdebug или аналогов, то можно посмотреть где именно возникают задержки и нагрузка.
joookleol, как часто обновляются данные?
Кешировать можно и на короткий промежуток времени, чтобы несколько активных соединений (читай посетителей) не лезли постоянно в БД.
Ну и смотрите explain ваших запросов.
Если у вас запросы без limit то это может очень сильно влиять на их производительность.
Ну и не факт вообще что именно бд является узким местом. Может у вас сложные расчеты есть на каждый ajax-запрос?
Либо вообще не в них дело.
Используйте профилирование
Для правильного вопроса надо знать половину ответа
Сразу после загрузки страницы получать весь массив точек, затем подключаться через вебсокет и получать новые значения сразу, как только они появляются.
Запрашивайте не всю базу, а ту часть которой нет.
При первом запросе загружайте все, кешируйте. При подгрузке, загружайте данные, которые младше данных, имеющихся в браузере на данный момент.