jey_val_star
@jey_val_star
Программист

Как ускорить выполнение SQL запроса?

Есть запрос который выполняется очень долго (более 1 мин)
SELECT n.nomin as name , 
	(
		SELECT count(cl.id) 
		FROM `ci_clubs` as cl
		WHERE cl.id in 
		(
			SELECT cl2.id FROM `ci_clubs` as cl2
			LEFT OUTER JOIN `ci_contes` as con2 ON (con2.id_club=cl2.id)
			LEFT OUTER JOIN `ci_group_cont` as gc2 ON (gc2.contes_id = con2.id)
			LEFT OUTER JOIN `ci_nomin_groups` as ng2 ON (ng2.group_id = gc2.group_contes_id)
			WHERE ng2.nomin_id = n.id
		
		)
	) as clubs,
	(
		SELECT count(con3.id) 
		FROM `ci_contes` as con3
		WHERE con3.id in 
		(
			SELECT con4.id FROM `ci_contes` as con4
			LEFT OUTER JOIN `ci_group_cont` as gc3 ON (gc3.contes_id = con4.id)
			LEFT OUTER JOIN `ci_nomin_groups` as ng3 ON (ng3.group_id = gc3.group_contes_id)
			WHERE ng3.nomin_id = n.id
		
		)
	) as contes, (3) as tour_id
	
FROM `ci_contes` con
LEFT OUTER JOIN `ci_group_cont` as gc ON (gc.contes_id=con.id)
LEFT OUTER JOIN `ci_nomin_groups` AS ng ON (ng.group_id=gc.group_contes_id)
LEFT OUTER JOIN `ci_nomin` AS n ON (n.id = ng.nomin_id)
 
WHERE n.fest=3 AND con.id = 37 AND  n.id is not null

ORDER by n.id DESC


На выходе получаю название номинаций, количество клубов, количество участников

Сама БД состоит из:
- клубов
- участников (1 участник принадлежит только одному клубу)
- группы (от 1 и до 41 участников в группе)
- номинаций

Причем один и тот же участник может быть в любой группе
А одна и та же группа может быть в любой номинации
Связь при этом получается:
участник - группа (множество к множеству - сделано через доп таблицу)
группа - номинация (множество к множеству - сделано через доп таблицу)

кол-во участников - 900
кол-во номинаций - 400

Итого вопрос: можно ли как-то ускорить данный запрос?
  • Вопрос задан
  • 327 просмотров
Решения вопроса 1
Stalker_RED
@Stalker_RED
Для начала почитать про индексы. Создать их, при необходимости. (это довольно легко)
Потом почитать про explain (это уже сложнее).
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
R0dger
@R0dger
Laravel/Yii/2 AngularJs PHP RESTful API
НЕ ПИХАЙТЕ В IN Select да еще и с JOIN.
выполняйте за два запроса. кешируйте и т.д.
Ответ написан
Комментировать
akalend
@akalend
программирую
представляете, что в SELECT .., ( SELECT count() ... ) , ...
на каждую строчку во внешнем селекции происходит выполнение подзапроса (внутреннего селекта). А у Вас их два или даже три, естественно будет тормозить.

Вариантов оптимизации море, нужно экспериментировать:
1) разбивка на более простые запросы, сборка результата на клиенте
2) написание хранимой процедуры (для MySQL это не очень хорошая затея) из простых запросов и созданием временных таблиц
Ответ написан
Комментировать
ravshanium
@ravshanium
аналитик, веб-программист
По идее должно быть как-то так:
SELECT n.nomin as name, count( DISTINCT cl.id ),  count( DISTINCT  con2.id )
  FROM `ci_nomin` AS n 
    LEFT OUTER  JOIN `ci_nomin_groups` as ng2 ON (  n.id = ng2.nomin_id )
    LEFT OUTER JOIN `ci_group_cont` as gc2 ON (  ng2.group_id = gc2.group_contes_id )
    LEFT OUTER JOIN `ci_contes` as con2 ON (  gc2.contes_id = con2.id )
    LEFT OUTER JOIN `ci_clubs` as cl2  ON (  con2.id_club = cl2.id )
GROUP BY n.nomin
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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