Какой из запросов более оптимальный?

Один запрос с подзапросами
SELECT * FROM users WHERE id IN ( SELECT user FROM pp1 where organization = 1) OR id IN ( SELECT user FROM pp2 where organization = 1) LIMIT 15;

Второй с джоинами
SELECT u.* FROM users u LEFT JOIN pp1 ON u.id = pp1.id and pp1.organization = 1 LEFT JOIN pp2 ON u.id = pp2.id and pp2.organization = 1 WHERE pp1.user IS NOT NULL OR pp2.user IS NOT NULL LIMIT 15;

Но вот когда добавляю сортировку допустим к запросу
SELECT * FROM users WHERE id IN ( SELECT user FROM pp1 where organization = 1) OR id IN ( SELECT user FROM pp2 where organization = 1) ORDER BY u.name LIMIT 15;

запрос раз в 5 медленней идёт
  • Вопрос задан
  • 604 просмотра
Пригласить эксперта
Ответы на вопрос 2
@alexalexes
Использование in нужно избегать, если вы в нем не прописываете статичные значения, или известное кол-во переменных с альтернативными вариантами.
Более живенько будет работать с обычными join:
SELECT u.* FROM users u 
JOIN pp1 ON u.id = pp1.id and pp1.organization = 1 
union
SELECT u.* FROM users u 
JOIN pp2 ON u.id = pp2.id and pp2.organization = 1
ORDER BY name
LIMIT 15

Или использовать exists в where - так вы планировщику даете понять, что можно не искать все варианты в подзапросе, а найти один, подходящий под условие.
SELECT u.* FROM users u 
where exists (select 1 from pp1 where u.id = pp1.id and pp1.organization = 1 )
     or exists (select 1 from pp2 where u.id = pp2.id and pp2.organization = 1 )
ORDER BY u.name
LIMIT 15

PS: Наличие однотипных таблиц pp1 и pp2 говорит о наличии ошибки проектирования базы данных. От видов сущностей pp у вас не должно плодится таблицы с pp. У таблицы pp должно быть свойство вида сущности, например pp_type_id и таблица-справочник pp_type - куда вы будете добавлять новый вид сущности, а не создавать новую таблицу.
Тогда запрос у вас будет выглядеть так:
SELECT u.*
   FROM users u 
where exists (select 1 
              from pp
             where u.id = pp.id
               and pp.organization = 1 
               and pp.pp_type_id in (1, 2) -- собственно, в таблице содержится все, что раньше находилось в pp1 и pp2, появилось поле, которое отличает разновидности записей
          )
ORDER BY u.name
LIMIT 15
Ответ написан
unfilled
@unfilled
я бы сделал так
select *
from users u
where 
    u.id = any (
        select id
        from pp1
        where organization = 1

        union all

        select id
        from pp2
        where organization = 1
    )
order by u.name
limit 15

если работает медленно - уже смотреть план выполнения
Ответ написан
Комментировать
Ваш ответ на вопрос

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

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