Как оптимизировать сложный запрос на нагруженной базе MYSQL?

12 3
FD
На сайте с 12.05.2017
Offline
71
656

Друзья всем привет! Имеем проект, в нем есть 2 динамически меняющиеся таблицы. По ним нужно делать селект с джойном.
Проблема в том, что проект загружен, этот запрос выполняется до 20к раз в секунду.
Проблема следующая, при невысокой нагрузке имеем продочную загрузку сервера и в целом живем. Но когда количество запросов подваливает к 10к в секунду, процессор начинает сильно нагружаться (до 100% по всем ядорам), селекты начинаю выполняться по несколько секунд, и в итоге происходит отказ в обслуживании.
Железо топовое, настроена репликация по 2м серверам, запись идет на мастер, все чтения со слейва:
Размеры таблиц - TaskFlow 200-300gb, Tasks 20gb
Сам запрос:
$acc - каждый запрос разный
Индексы все есть, до 5к запросов в секунду держит впринципе без проблем

SELECT 
  task.id, 
  task.remains
FROM 
  Task task 
WHERE 
  task.status = 'active' 
  AND task.type = 'follow_profile' 
  AND task.provider = 'insta' 
  AND task.cat = 3 
  AND NOT EXISTS(
  SELECT 1 FROM  TaskFlow flow 
  WHERE 
    flow.url_id = task.url_id 
    AND flow.executor_acc_id = $acc 
  );
ORDER BY task.id ASC
LIMIT 300

Индексы:

Task ( status, type, provider, cat )
TaskFlow (executor_acc_id, url_id )

Суть: При количестве запросов селект и инсерт в них примерно 3000+ в секунду, все ок.
Как только количество переваливает за 4000+ начинает сильно расти нагрузка на процессоры слейвов, селекты начинают выполнятся с задержкой в статусе sending data и их копится огромное количество если смотреть по show processlist и начинает расти отставание между мастером и слейвом. Соответственно все тупит и работает некорректно.
Не прекращается пока не ограничить поступление запросов. Как только останавливаем инсерты и селекты, все за пару секунд возвращается в норму


Explain

id      select_type     table   type    possible_keys   key     key_len ref     rows    Extra
1       PRIMARY task    ref     stat_task,getlist,getlist_bot   getlist_bot     6       const,const,const,const 8731    Using index condition; Using where
id      select_type     table   type    possible_keys   key     key_len ref     rows    Extra
2       DEPENDENT SUBQUERY      flow    index_subquery  user_url_executor       user_url_executor       8       func,const      1       Using index; Using where


Подскажите куда копать. Спасибо!

UPD: Если увеличивать LIMIT в выборке, нагрузка значительно возрастает.

НАКРУТКА INSTAGRAM (https://instagram777.ru) - Смешные цены!
SS
На сайте с 28.05.2008
Offline
142
#1

Я бы рекомендовал отказаться от текстовых индексов и заменить их цифровыми, если это возможно.

Т.е. вместо active и deactive использовать 0 и 1, вместо insta, vk, fb использовать 1,2,3 итд.

Также можно попробовать создать индексы по двум (или более) полям, если есть такие сочетания, которые встречаются очень часто. Например 

task.status = 'active' AND task.type = 'follow_profile'

если в большинстве запросов status = active и type = follow_profile, то создать совместный индекс по ним и посмотреть на результаты.

Также если БД Myisam, то перейти на Innodb

LEOnidUKG
На сайте с 25.11.2006
Offline
1731
#2
Не прекращается пока не ограничить поступление запросов. Как только останавливаем инсерты и селекты, все за пару секунд возвращается в норму
У вас таблицы похоже в  Myisam из-за этого идёт блокировка таблицы при записи.
✅ Мой Телеграм канал по SEO, оптимизации сайтов и серверов: https://t.me/leonidukgLIVE ✅ Качественное и рабочее размещение SEO статей СНГ и Бурж: https://getmanylinks.ru/
FD
На сайте с 12.05.2017
Offline
71
#3
SmartSEO #:

Я бы рекомендовал отказаться от текстовых индексов и заменить их цифровыми, если это возможно.

Т.е. вместо active и deactive использовать 0 и 1, вместо insta, vk, fb использовать 1,2,3 итд.

Также можно попробовать создать индексы по двум (или более) полям, если есть такие сочетания, которые встречаются очень часто. Например 

если в большинстве запросов status = active и type = follow_profile, то создать совместный индекс по ним и посмотреть на результаты.

Также если БД Myisam, то перейти на Innodb

Тип полня этих таблиц ENUM

FD
На сайте с 12.05.2017
Offline
71
#4
LEOnidUKG #:
У вас таблицы похоже в  Myisam из-за этого идёт блокировка таблицы при записи.

innodb

FD
На сайте с 12.05.2017
Offline
71
#5
SmartSEO #:

Я бы рекомендовал отказаться от текстовых индексов и заменить их цифровыми, если это возможно.

Т.е. вместо active и deactive использовать 0 и 1, вместо insta, vk, fb использовать 1,2,3 итд.

Также можно попробовать создать индексы по двум (или более) полям, если есть такие сочетания, которые встречаются очень часто. Например 

если в большинстве запросов status = active и type = follow_profile, то создать совместный индекс по ним и посмотреть на результаты.

Также если БД Myisam, то перейти на Innodb

Task ( status, type, provider, cat )
TaskFlow (executor_acc_id, url_id )

составные индексы созданы по всем полям

LEOnidUKG
На сайте с 25.11.2006
Offline
1731
#6
FrancisDarroze #:

innodb

Вставки идут как? Есть ещё предположения, что индексы пересчитываются и делать вставки надо через COMMIT, если они групповые.

LEOnidUKG
На сайте с 25.11.2006
Offline
1731
#7
Индексы все есть, до 5к запросов в секунду держит впринципе без проблем
Вообще конечно задачка интересная т.к. нужно и железо смотреть и настройки и версию mysql и т.д.
FD
На сайте с 12.05.2017
Offline
71
#8
LEOnidUKG #:
Вообще конечно задачка интересная т.к. нужно и железо смотреть и настройки и версию mysql и т.д.

железо - 2 слейва с которых читаем, достаточно серьезные

FD
На сайте с 12.05.2017
Offline
71
#9
LEOnidUKG #:

Вставки идут как? Есть ещё предположения, что индексы пересчитываются и делать вставки надо через COMMIT, если они групповые.

инсерты идут каждый запрос, сначала основной селект, по результатам его инсерт в таскфлоу

L
На сайте с 10.02.2015
Offline
223
#10

1. Покажите EXPLAIN

2. Вот сейчас у себя написан запрос с NOT EXISTS и с LEFT JOIN

NOT EXISTS не использовал индексов, в то время как  LEFT JOIN использовал и в Extra числилось "Not exists"

12 3

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий