grigor007
@grigor007
http://goldapp.ru

Какие существуют способы оптимизации часто идуших MySQL запросов на выборку?

Здравствуйте,

например есть сайт с посещаемостью. И там в реальном времени у каждого пользователя обновляется индикатор новых событий

Скажите пожалуйста, какие есть способы для оптимизации таких запросов от каждого пользователя ( раз в минуту )? Просто был проект и я так и не дошел до решения этой проблемы. А запросы выполнялись долго ( так как было много пользователей, которые использовали ту же таблицу в б. д. при поиске )

Спасибо
  • Вопрос задан
  • 3354 просмотра
Пригласить эксперта
Ответы на вопрос 4
FanatPHP
@FanatPHP
Чебуратор тега РНР
Сферический вопрос в вакууме, причём без возможности уточнения, поскольку «проект был».
«медленные запросы» — насколько медленные?
«сайт с посещаемостью» — с какой посещаемостью?
«потому что запросы на поиск» — так может, это поиск вынести отдельно на Сфинкс?

То есть, выяснить, что там — кривая настройка сервера mysql, кивые таблицы или кривые запросы — не представляется возможным.
Но вопрос, как всегда, формируется в самом общем виде — «где тот волшебный гвоздь, по которому 1 раз ударить — и всё сразу залетает?»

Ну ок. В самом общем виде оптимизация запросов (неважно — частых или нечастых) заключается в оптимизации запросов.
Оптимизированный запрос выполняется (допустим) 0.001 секунды. То есть, БД может обслужить 60 тысяч одновременно сидящих пользователей.

Берем EXPLAIN и смотрим. Если он говорит, что с запросом все окей, просматриваем ровно столько записей, сколько нужно — 5-10, но все равно запрос исполняется медленно (насколько конкретно медленно — в секундах?) то смотрим, SHOW ENGINE [engine] STATUS. Там уже надо опять же смотреть по месту, решать, чего серверу не хватает.

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

То есть, действуем как программист — а именно, разбираемся с конкретной проблемой, и ищем решение конкретно для неё.
А не придумываем от балды заплатку для лечения симптома, оставляя болезнь развиваться и дальше.

Кэширование, как и любая другая денормализация данных, всегда чревато проблемами и неудобствами. И это должно быть средство последней надежды, когда всё остальное уже сделано.
Ответ написан
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Давайте по порядку.
У вас есть посещаемый ресурс, где пользователям должны в режиме реального времени приходить уведомления о чем-то. Ну мол например о непрочитанных сообщениях. Для этого я так понимаю вы ежеминутно опрашиваете сервер, и оттуда и появляются кучи одинаковых запросов. Поидее если mySQL настроен нормально, то все эти запросы он будет пытаться кешировать сам. У вас точно есть проблемы с производительностью БД в этом ключе?

С другой стороны, самый оптимальный способ решить эту задачу: WebSockets/long pooling. Реализовать простенький сервер на каком node.js + scocket.io. Как шину данных поставить какой rabbitmq или чего подобное. В случае сообщений, при отправлении сообщения другому пользователю, в очередь отправляется сообщение. Оно принимается push-сервером и, если у нас есть соединение с нужным пользователем, отправляем ему уведомление. При таком подходе мы имеем: данные уходят с минимальными задержками. Уменьшается нагрузка на сервер за счет уменьшения количества запросов (push сервер просто держит соединение и работает только с небольшим количеством за раз). Ну и последнее — масштабируемость за счет rabbitmq: из основного приложения всего лишь отправляются в очередь небольшие сообщения. А то как оно паралелит сообщения и их обработка вынесены в rabbitmq. Меньшая связанность систем. Да и готовых реализации хватает.
Ответ написан
@uzzz
Если индикатор новых событий общий для всех пользователей (например какой-нибудь глобальный feed на сайте), то разумным будет кэшировать результат в памяти используя memcached или redis.
Ответ написан
@rozhik
Если кэширование запросов не возможно то есть несколько путей (по степени эффективности ниже — эффективнее):
1. С помощью explain SQL посмотреть и удостоверится, что все запросы и индексы оптимальны. Если не оптимальны — оптимизировать.
2. Использовать Шардинг (разбить таблицу на несколько)
3. Кэширование
4. Использование push-pub сервиса
5. использование middleware (на ноде, перле, жаве итп обернуть все операции с таблицей в RPC. требование к middleware — внутреннее кэширование всех данных, отправка только insert/update на mysql)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы