LINUX.ORG.RU

Тормоза после вложенных запросов MySQL


0

1

Вот такой запрос отрабатывает за ~0.06 секунды:

SELECT COUNT(DISTINCT c.layer) FROM vulnerability AS v
JOIN vulnerability_configuration_mask AS vc ON v.id = vc.vulnerability_id
JOIN configuration_mask_component AS cc ON cc.configuration_mask_id = vc.configuration_mask_id
JOIN component AS c ON c.id = cc.component_id
WHERE v.id = 3

, меняя «v.id = 3» на «v.id = <любой id>», все равно все «летает».

Хочу получить такой результат для всех v сразу. Делаю так:

SELECT vmain.id,
(
	SELECT COUNT(DISTINCT c.layer) FROM vulnerability AS v
	JOIN vulnerability_configuration_mask AS vc ON v.id = vc.vulnerability_id
	JOIN configuration_mask_component AS cc ON cc.configuration_mask_id = vc.configuration_mask_id
	JOIN component AS c ON c.id = cc.component_id
	WHERE v.id = vmain.id
)
FROM vulnerability AS vmain

, и начинаются дикие тормоза. Считалось около 2 минут - я прервал запрос. С LIMIT 10 в конце считается за 36 секунд.

Почему после добавления внешнего запроса скорость так упала и как это исправить?

★★

Не знаю как насчёт исправления, но почему бы не сделать просто:

SELECT COUNT(DISTINCT c.layer) FROM vulnerability AS v
JOIN vulnerability_configuration_mask AS vc ON v.id = vc.vulnerability_id
JOIN configuration_mask_component AS cc ON cc.configuration_mask_id = vc.configuration_mask_id
JOIN component AS c ON c.id = cc.component_id

Оно же тогда будет для всех значений v.id.

А так по идее получается, что для таблицы из N значений выполняется N запросов.

ssvda
()

Я хреновый специалист по SQL, но возможно использование транзакций тебе поможет.

START TRANSACTION;
SELECT ....;
COMMIT;

m0rph ★★★★★
()

100% индекс не тот берет. просто используй postgresql.

quest ★★★★
()
Ответ на: комментарий от m0rph

Я хреновый специалист по SQL, но возможно использование транзакций тебе поможет.

Действительно хреновый - транзакции имеют отношение к изменению данных. Селекту они ортогональны.

theos ★★★
()
Ответ на: комментарий от theos

Действительно хреновый - транзакции имеют отношение к изменению данных.

Буду знать, спасибо.

m0rph ★★★★★
()
Ответ на: комментарий от ssvda

Да, усё верно... ТС засунул подзапрос в заголовок, на место столбца. Значение подзапроса вычисляется для каждой строки, потому что:

WHERE v.id = vmain.id
Подзапрос в заголовке выгоден если его значение не зависит от значений строк основного набора данных или если он формируется по небольшой индексированной таблице, которая может быть откеширована в памяти.

Насколько я понял, ТС-у нужно для каждого vulnerability.id найти количество уникальных c.layer. Задачка из книги «SQL для чайников».

SELECT    vulnerability.id, COUNT(DISTINCT c.layer) 
FROM      vulnerability AS v JOIN 
	      vulnerability_configuration_mask AS vc ON v.id = vc.vulnerability_id JOIN
              configuration_mask_component AS cc ON cc.configuration_mask_id = vc.configuration_mask_id JOIN
              component AS c ON c.id = cc.component_id
group by vulnerability.id

dmitryalexeeff
()

надо попробовать

SELECT COUNT(c.layer), v.id FROM vulnerability AS v
JOIN vulnerability_configuration_mask AS vc ON v.id = vc.vulnerability_id
JOIN configuration_mask_component AS cc ON cc.configuration_mask_id = vc.configuration_mask_id
JOIN component AS c ON c.id = cc.component_id
GROUP BY COUNT(c.layer)
bk_ ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.