Нужна помощь разобраться с медленным mysql запросом

Все вопросы/проблемы по установке и использовании.
Ответить
Аватара пользователя
support
Техническая поддержка
Сообщения: 7661
Зарегистрирован: 19 окт 2014, 18:22
Имя: Харчишин Сергей
Откуда: Крым, Евпатория

Нужна помощь разобраться с медленным mysql запросом

Сообщение 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 файл с данными, можно попробовать у себя

подскажите, пожалуйста, что делаю не так и есть ли возможность ускорить запрос в таком виде?
Вложения
explain.png
test_data.sql
(448.03 КБ) 295 скачиваний
pentiumd2013
Сообщения: 4
Зарегистрирован: 26 авг 2016, 00:46
Имя: Nikita

Re: Нужна помощь разобраться с медленным mysql запросом

Сообщение 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)
pentiumd2013
Сообщения: 4
Зарегистрирован: 26 авг 2016, 00:46
Имя: Nikita

Re: Нужна помощь разобраться с медленным mysql запросом

Сообщение pentiumd2013 »

app_related_items - здесь есть составной индекс по entities_id, items_id, related_entities_id ?
Аватара пользователя
support
Техническая поддержка
Сообщения: 7661
Зарегистрирован: 19 окт 2014, 18:22
Имя: Харчишин Сергей
Откуда: Крым, Евпатория

Re: Нужна помощь разобраться с медленным mysql запросом

Сообщение support »

К сожалению не подойдет, результат получается другой, но работает быстрее:)
pentiumd2013
Сообщения: 4
Зарегистрирован: 26 авг 2016, 00:46
Имя: Nikita

Re: Нужна помощь разобраться с медленным mysql запросом

Сообщение 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 ... Логику не меняет, просто покороче
Последний раз редактировалось pentiumd2013 26 авг 2016, 19:17, всего редактировалось 1 раз.
Аватара пользователя
support
Техническая поддержка
Сообщения: 7661
Зарегистрирован: 19 окт 2014, 18:22
Имя: Харчишин Сергей
Откуда: Крым, Евпатория

Re: Нужна помощь разобраться с медленным mysql запросом

Сообщение support »

Еще раз спасибо!
Аватара пользователя
support
Техническая поддержка
Сообщения: 7661
Зарегистрирован: 19 окт 2014, 18:22
Имя: Харчишин Сергей
Откуда: Крым, Евпатория

Re: Нужна помощь разобраться с медленным mysql запросом

Сообщение 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, то таким запросом она не исключается из выборки, а мне нужно ее исключить. Что можно сделать?
pentiumd2013
Сообщения: 4
Зарегистрирован: 26 авг 2016, 00:46
Имя: Nikita

Re: Нужна помощь разобраться с медленным mysql запросом

Сообщение 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)
)
Аватара пользователя
support
Техническая поддержка
Сообщения: 7661
Зарегистрирован: 19 окт 2014, 18:22
Имя: Харчишин Сергей
Откуда: Крым, Евпатория

Re: Нужна помощь разобраться с медленным mysql запросом

Сообщение 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 и время незначительно увеличивается при добавлении новых фильтров, в отличии от вложенных запросов.
Ответить