AJAX - MySQL Query Flooding Server - PullRequest
       12

AJAX - MySQL Query Flooding Server

0 голосов
/ 27 апреля 2020

Я занимаюсь этим уже несколько дней, пытаясь различными способами снизить нагрузку на процессор на 95-135% из-за недавнего сценария AJAX, вызывающего этот запрос:

SELECT COUNT(*) as total FROM users WHERE last_access >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) ORDER BY last_access DESC LIMIT 16

И я попытался COUNT(id) сократить время сканирования таблицы, я добавил LIMIT и ORDER BY, я думаю, что это улучшилось, но я не могу сказать. Я отслеживаю top -P на моем BSD-боксе, и процессор довольно быстро зашкаливает, почти убивая apache, хотя полагаюсь на это при тестировании запросов.

У нас есть Бит jquery, который запрашивает скрипт AJAX и возвращает количество таблиц в соответствии с последними пользователями в сети с 15-секундным интервалом на стороне jquery (1 минута в операторе запроса). Это было хорошо в течение дня, затем заметил, что сервер работал сверхурочно, и фанаты отказались от работы.

В итоге мы удалили MySQL 5.7 и установили MariaDB 12.4 - и это имело огромное значение, однако, когда он работал при сниженной нагрузке на ~ 20% ЦП, он тоже боролся .. так что запрос плохой. Я отключил скрипт и, конечно же, процессор снизился до 15-30% avg, однако это большая часть UX нашего сайта. Это просто сообщает (455 онлайн), например, и обновляет текст каждые 15 секунд (динамически).

Мой вопрос ... из-за 15-секундного интервала совпадений с оператором SELECT(*) в таблице 9600 записей , как я могу оптимизировать это, чтобы сервер SQL не обрабатывал sh и не высасывал всю доступную память?

Я не включил скрипт, так как он прекрасно работает запрос является проблемой, но предоставит при необходимости.

Это наш единственный AJAX скрипт на сайте. Другие AJAX звонки не совершаются.

С уважением,

Ответы [ 2 ]

2 голосов
/ 27 апреля 2020

Я не думаю, что сам запрос SQL является проблемой здесь. Добавление ORDER BY и LIMIT не должно иметь никакого значения, так как есть только одна строка для сортировки и ограничения. Вы можете подумать о том, чтобы добавить индекс для столбца last_access.

В зависимости от трафика вашего сайта c, я думаю, что проблема в том, как вы спроектировали свою систему. Вы говорите, что клиент запрашивает ваш сервер каждые 15 секунд, который запрашивает у вашей базы данных количество пользователей в последнюю минуту. Представьте, что в сети 1000 пользователей, в этом случае у вас будет 66 запросов в секунду.

В этом случае вам следует рассмотреть возможность внедрения кэша. Вы пометили свой пост как PHP, Memcached , который довольно просто реализовать в PHP. Кэшируйте ваш запрос SQL на 15 секунд, и вместо этого ваш сервер баз данных будет иметь только 0,06 запроса в секунду.

Для таблиц MyISAM COUNT (*) оптимизирован для очень быстрого возврата, если SELECT извлекает из одной таблицы другие столбцы не извлекаются, а предложение WHERE отсутствует. https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_count

1 голос
/ 28 апреля 2020
SELECT  COUNT(*) as total
    FROM  users
    WHERE  last_access >= DATE_SUB(NOW(), INTERVAL 1 MINUTE)
    --  ORDER BY  last_access DESC  -- Toss; one output row, nothing to sort
    --  LIMIT  16  -- Toss, only output row

Обязательно имейте это на столе

INDEX(last_access)

COUNT(id), во всяком случае, медленнее. Это то же самое, что и COUNT(*), плюс проверка id на наличие NOT NULL.

Сколько существует различных потоков?

Давайте посмотрим, что запрос принимает -

  1. Запрос AJAX попадает на веб-сервер.
  2. Он отправляет запрос «дочернему элементу» или «потоку», который, вероятно, уже ожидает действия.
  3. Если ребенку требуется PHP, он запускает этот процесс.
  4. , который подключается к MySQL.
  5. Запрос выполняется. Если у вас есть индекс, этот шаг является тривиальным.
  6. Завершение работы.

Другими словами, вы исследовали, какой процесс занимает большую часть ЦП?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...