Это действительно уродливый запрос. Помимо того факта, что есть ошибки, вы игнорируете множество лучших практик, и хотя это может существенно не улучшить вашу производительность, при написании запросов, которые легко читать, значительно улучшится ваша способность поддерживать запросы в будущем. Прежде всего: если вы используете псевдонимы, вы должны использовать их последовательно, как путем наложения всех ваших таблиц, так и путем префикса всех ваших столбцов. Кроме того, вы должны действительно думать о расстоянии. Просто изменив эти две вещи (и несколько других вопросов), мы получим следующее:
select i.item_id
from Item i,
(select ad.address_id,
il.item_location_id
from address ad,
Item_location il
where
ad.street_nm like '%zebra%' and ad.street_nbr = 333
and il.address_id = ad.address_id) addr
where
addr.item_location_id = i.location_a
or addr.item_location_id = i.location_b
Wow! Это настолько читаемо. Теперь я могу ясно видеть, что вы используете устаревшую версию соединений таблиц, и это должно измениться на явное соединение (стандартизация yay). Кроме того, я могу ясно видеть, что вам не нужен подзапрос для этого запроса. Удаление подзапроса, скорее всего, улучшит производительность вашего запроса (это может быть только немного, но нам нравится любая и вся прибыль). Устанавливаем эти проблемы:
select i.item_id
from Item i
join address ad
on (addr.item_location_id = il.location_a
or addr.item_location_id = il.location_b)
join Item_location il
on il.address_id = ad.address_id
where
ad.street_nm like '%zebra%' and ad.street_nbr = 333
Вдруг это выглядит намного лучше. Теперь мы можем действительно отточить самую большую проблему (по-моему) в вашем запросе.
on (addr.item_location_id = il.location_a
or addr.item_location_id = il.location_b)
Забавный факт, потому что вы не выбирали или наложений ничего как location_a и location_b в исходном запросе, он не выполнил бы и вы получили бы ошибку. Я просто собираюсь идти вперед и думаю, что это убивает ваш запрос. Первоначально я не мог видеть этот большой жир or
, висящий в качестве условия соединения. Моя рекомендация состоит в том, чтобы разделить это на двух запросов и бросить в союз все:
select i.item_id
from Item i
join address ad
on addr.item_location_id = il.location_a
join Item_location il
on il.address_id = ad.address_id
where
ad.street_nm like '%zebra%' and ad.street_nbr = 333
union all
select i.item_id
from Item i
join address ad
on addr.item_location_id = il.location_b
join Item_location il
on il.address_id = ad.address_id
where
ad.street_nm like '%zebra%' and ad.street_nbr = 333
Без индексации, я думаю, что этот запрос будет вашим лучшим выбором с точки зрения производительности. Даже если это не ускорит работу слишком много, посмотрите, насколько красивее! Будущие разработчики вашей организации будут вам благодарны.
[Плохие привычки пинать: использование JOIN-файлов в старом стиле] (http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old-style- присоединяется.aspx) - стиль старого стиля * разделенный запятыми список таблиц * был заменен на * правильный * ANSI 'JOIN' синтаксис в ANSI - ** 92 ** SQL Standard (** более 20 лет ** назад) и его использование не рекомендуется –
@marc_s, но я видел дискуссию, где в переполнении стека на том же самом. И производительность не имеет большого значения для более старого способа присоединения к ANSI-соединению. (Ofcoz я буду копать вашу ссылку дальше на том же самом). – Zeus
Сколько строк в каждой таблице, соответственно, сколько строк вы ожидаете получить? –