Страница 1 из 1
Нужна помощь разобраться с медленным mysql запросом
Добавлено: 25 авг 2016, 22:20
support
Друзья, помогите разобраться с медленным запросом.
Есть три таблицы
app_entity_49 - данные
app_entity_55 - данные
app_related_items - таблица для связей
Сам запрос
Код: Выделить всё
select
((select SUM(func.field_538*func.field_534) from app_entity_49 func where func.id>0 and (
func.id in (select ri.related_items_id as related_items_id from app_related_items ri where (ri.entities_id = '55' and ri.items_id = e.id and ri.related_entities_id='49'))
or
func.id in (select ri.items_id as related_items_id from app_related_items ri where (ri.related_entities_id='55' and ri.related_items_id=e.id and ri.entities_id = '49')))
)
) as field_653
from app_entity_55 e
То есть из app_entity_55 выбираем данные, где считаем сумму неких полей из app_entity_49 и сумму считаем только в тех записях где установлена связь в таблице app_related_items
выборка из app_related_items очень замедляет запрос
прикрепил скриншот explain и sql файл с данными, можно попробовать у себя
подскажите, пожалуйста, что делаю не так и есть ли возможность ускорить запрос в таком виде?
Re: Нужна помощь разобраться с медленным mysql запросом
Добавлено: 26 авг 2016, 00:47
pentiumd2013
Такой запрос не подойдет?
SELECT SUM(func.field_538*func.field_534) field_653
FROM app_entity_55 e
INNER JOIN app_related_items ri ON(ri.entities_id = '55' AND ri.items_id = e.id AND ri.related_entities_id='49')
INNER JOIN app_entity_49 func ON(func.id=ri.related_items_id OR func.id=ri.items_id)
Re: Нужна помощь разобраться с медленным mysql запросом
Добавлено: 26 авг 2016, 00:51
pentiumd2013
app_related_items - здесь есть составной индекс по entities_id, items_id, related_entities_id ?
Re: Нужна помощь разобраться с медленным mysql запросом
Добавлено: 26 авг 2016, 07:40
support
К сожалению не подойдет, результат получается другой, но работает быстрее:)
Re: Нужна помощь разобраться с медленным mysql запросом
Добавлено: 26 авг 2016, 15:29
pentiumd2013
Код: Выделить всё
SELECT SQL_NO_CACHE
SUM(IFNULL(func.field_538, 0) * IFNULL(func.field_534, 0)) + SUM(IFNULL(func2.field_538, 0) * IFNULL(func2.field_534, 0)) field_653
FROM app_entity_55 e
LEFT JOIN app_related_items ri ON(ri.entities_id =55 AND ri.items_id = e.id AND ri.related_entities_id=49)
LEFT JOIN app_related_items rie ON(rie.related_entities_id =55 AND rie.items_id = e.id AND rie.related_entities_id=49)
LEFT JOIN app_entity_49 func ON(func.id=ri.related_items_id)
LEFT JOIN app_entity_49 func2 ON(func2.id=rie.items_id)
GROUP BY e.id
Можно вместо IF использвать IFNULL ... Логику не меняет, просто покороче
Re: Нужна помощь разобраться с медленным mysql запросом
Добавлено: 26 авг 2016, 16:02
support
Еще раз спасибо!
Re: Нужна помощь разобраться с медленным mysql запросом
Добавлено: 28 дек 2016, 16:33
support
Никита, прошу помочь еще с одним запросом.
Есть таблица app_entity_30 где хранятся некие записи и есть таблица app_entity_30_values где хранятся значения, например статусов.
Задача: нужно выбрать все записи где ID статуса 93 и 88 (запись может быть назначена на несколько статусов)
Раньше использовал вложенный запрос
Код: Выделить всё
select e.* from app_entity_30 e where ((select count(*) from app_entity_30_values as cv where cv.items_id=e.id and cv.fields_id='269' and cv.value in (93,88)) >0)
Но это оказалось очень медленно при большом количестве записей и если таких запросов несколько штук.
Переделал с использованием left join что значительно ускорило выборку
Код: Выделить всё
select e.* from app_entity_30 e left join app_entity_30_values ev on ev.items_id=e.id and ev.fields_id=269 where ((ev.value in (93,88)))
Но вот столкнулся с проблемой когда нужно выбрать все записи и исключить те где ID статуса 93 и 88
Раньше было так:
Код: Выделить всё
select e.* from app_entity_30 e where ((select count(*) from app_entity_30_values as cv where cv.items_id=e.id and cv.fields_id='269' and cv.value in (93,88)) =0)
Пробую так
Код: Выделить всё
select e.* from app_entity_30 e left join app_entity_30_values ev on ev.items_id=e.id and ev.fields_id=269 where ((ev.value not in (93,88)))
но работает не так как нужно, к примеру если запись назначена на три статуса 93 и 88 и 100, то таким запросом она не исключается из выборки, а мне нужно ее исключить. Что можно сделать?
Re: Нужна помощь разобраться с медленным mysql запросом
Добавлено: 28 дек 2016, 20:24
pentiumd2013
Код: Выделить всё
SELECT *
FROM app_entity_30
WHERE id NOT IN(
SELECT items_id
FROM app_entity_30_values
WHERE fields_id=269
AND value IN(93,88)
)
Re: Нужна помощь разобраться с медленным mysql запросом
Добавлено: 28 дек 2016, 21:12
support
Вообщем, чтоб использовать left join и исключить значения придумал такую штуку
Код: Выделить всё
select e.* from app_entity_30 e left join app_entity_30_values ev on (ev.items_id=e.id and ev.fields_id=269 and ev.value in (87,88)) where e.id>0 and ((ev.id is null))
То есть при left join указываем "and ev.value in (87,88)" и в таком случаи во всех остальных записях "ev.id is null"
В целом проблема обнаружилась с использованием большого количества фильтров, к примеру задачи можно фильтровать по полям: Статус, Тип, Назначен На и т.д. и каждый раз вставлялся вложенный запрос.
К примеру 3 вложенных запроса и скрипт выполняется уже 0.0143 и это всего при нескольких тысяч записей.
С использованием left join аналогичный запрос выполняется 0.0040 и время незначительно увеличивается при добавлении новых фильтров, в отличии от вложенных запросов.