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

Друзья всем привет! Имеем проект, в нем есть 2 динамически меняющиеся таблицы. По ним нужно делать селект с джойном.
Проблема в том, что проект загружен, этот запрос выполняется до 20к раз в секунду.
Проблема следующая, при невысокой нагрузке имеем продочную загрузку сервера и в целом живем. Но когда количество запросов подваливает к 10к в секунду, процессор начинает сильно нагружаться (до 100% по всем ядорам), селекты начинаю выполняться по несколько секунд, и в итоге происходит отказ в обслуживании.
Железо топовое, настроена репликация по 2м серверам, запись идет на мастер, все чтения со слейва:
Размеры таблиц - TaskFlow 200-300gb, Tasks 20gb
Сам запрос:
$acc - каждый запрос разный
Индексы все есть, до 5к запросов в секунду держит впринципе без проблем
SELECT 
                task.id,
                task.dc,
                task.provider,
                task.type,
                task.url,
                task.cost,
                task.cost_bot,
                task.last_start_msec,
                task.url_id,
                task.remains,
                task.cat
            FROM Task task
         LEFT JOIN TaskFlow flow ON flow.url_id = task.url_id AND flow.executor_acc_id = $acc
            WHERE task.status = 'active'
             AND task.type = 'follow_profile'  AND task.provider = 'insta'  AND task.cat = 3  AND flow.dt_start IS NULL


explain:
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	task	ref	stat_task,getlist,getlist_bot	getlist_bot	6	const,const,const,const	8625	Using index condition
1	SIMPLE	flow	ref	user_url_executor	user_url_executor	8	admin_insta.task.url_id,const	1	Using where; Using index; Not exists

Что делать подскажите? Кеширования на уровне редис или других средств пока откладываем в сторону. Слишком много придется для этого переделывать.
Спасибо!
  • Вопрос задан
  • 496 просмотров
Решения вопроса 1
rozhnev
@rozhnev Куратор тега MySQL
Fullstack programmer, DBA, медленно, дорого
Так как из второй таблицы данные не выбираются - попробуйте (NOT EXISTS):
SELECT 
  task.id, 
  task.dc, 
  task.provider, 
  task.type, 
  task.url, 
  task.cost, 
  task.cost_bot, 
  task.last_start_msec, 
  task.url_id, 
  task.remains, 
  task.cat 
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 
  );
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@rPman
если update запросов на порядок меньше чем запросов на select, то типовой способ ускорения последних за счет замедления update - исполнение запросов select заранее, складывая их результат в специальную табличку тригерами

так же хорошим подходом является кеширование результатов на бакэнде, не важно как, главное в оперативной памяти, и инвалидировать кеш на update-ах.

p.s. сразу бросаются хранение типов и статусов в строках, переделай в числа, должно заметно уменьшить базы данных, уменьшить объем базы и индексов.
лучше всего enum
Ответ написан
Ваш ответ на вопрос

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

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