SQL как оптимизировать запрос?

132
08 августа 2019, 22:40

Есть следующий запрос:

SELECT id, slug FROM medicine m WHERE
EXISTS(SELECT medicine_id FROM medicines_components WHERE medicine_id = m.id)
AND EXISTS(
    SELECT id FROM medicine m2 WHERE 
    EXISTS(SELECT medicine_id FROM medicines_countries WHERE medicine_id = m2.id AND country_id = 94)
    AND (SELECT COUNT(medicine_id) FROM medicines_components WHERE medicine_id = m2.id) = (SELECT COUNT(medicine_id) FROM medicines_components WHERE medicine_id = m2.id AND component_id IN (SELECT GROUP_CONCAT(component_id SEPARATOR ',') FROM medicines_components WHERE medicine_id = m.id))
)

Пример таблицы medicine:

id | slug
1  | str1
2  | str2

Пример таблицы medicines_components:

medicine_id | component_id
1           | 1
1           | 2
1           | 3
2           | 1

Пример таблицы medicines_countries:

medicine_id | country_id
1           | 1
1           | 2
2           | 1
2           | 3

Т.е. суть в том чтобы в таблице medicine находить лекарства(записи) у которых есть аналоги с таким же составом(компонентами medicine_components) которые есть в выбранной стране (medicine_countries). Сейчас в таком виде запрос выполняется очень долго, можно ли его как-то оптимизировать?

Answer 1

Если я правильно понял задачу, то вам требуется что то в этом роде:

SELECT a.slug, a.medicine_id
  FROM (
    SELECT m.slug, c.medicine_id, group_concat(component_id order by component_id) comp
      FROM medicines_components c, medicine m
     WHERE m.id=c.medicine_id
     GROUP BY c.medicine_id, m.slug
  ) a, (
    SELECT c.medicine_id, group_concat(component_id order by component_id) comp
      FROM medicines_components c, medicines_countries co
     WHERE co.medicine_id=c.medicine_id and co.country_id = 1
     GROUP BY c.medicine_id
  ) b where a.medicine_id!=b.medicine_id and a.comp=b.comp

Для дальнейшей оптимизации надо смотреть план выполнения запроса на реальных данных и добавлять индексы по необходимости. Если это не помогает, то надо смотреть в сторону внесения избыточности в БД и например хранения списка компонентов в таком виде как его сейчас собирает group_councat но в виде текстового поля в таблице medicine (разумеется в дополнение к таблице medicines_components) с поддержанием правильности этого значения триггерами.

READ ALSO
Как проверить наличие значения в базе данных в LUA

Как проверить наличие значения в базе данных в LUA

пишу скрипт на LUA, нужно решить такую задачуСуществует таблица в базе, в ней имеются колонки "Account" и "Model" и мне нужно узнать существует ли определенное...

120
Работа с текстом, граммотное оформление

Работа с текстом, граммотное оформление

Доброе время сутокХотел бы узнать, как в html грамотно записать код, чтобы потом обратиться к этим строкам в css

141
Как удалить height у img

Как удалить height у img

При выводе миниатюры WordPress добавляет ему width="230" height="300" по размеру картинки, но они мне очень мешают (ставлю сетку масонри)Как можно их удалить,...

127