Показаны сообщения с ярлыком оптимизация. Показать все сообщения
Показаны сообщения с ярлыком оптимизация. Показать все сообщения

пятница, 22 июля 2011 г.

MSSQL : Оптимизация запросов - убираем корреляцию в запросах.

Собственно нашел давно картинку, которая очень помогает в решении задач по оптимизации.
Например когда надо проверить (не)существование значений в другой таблице по заданным параметрам.

Самый простой вариант НЕ ПРАВИЛЬНЫХ запросов выглядит следующим образом
Вывести строки из t1, на которые есть ссылки в таблице t2
select * from t1
where exists(select * from t2 where t2.t1id = t1.id)

или на оборот,
select * from t1
where not exists(select * from t2 where t2.t1id = t1.id)


некоторые программисты начали пытаться ускорить код следующиими вариантами
select * from t1
where exists(select top 1 1 from t2 where t2.t1id = t1.id)

или на оборот,
select * from t1
where not exists(select top 1 1 from t2 where t2.t1id = t1.id)


Честно говоря я понимаю что есть ситуации когда без таких конструкций не обойтись, и в моей практике такое тоже встречалось. Но все же лучше пользоваться "умножения" таблиц
Получение строк, на которые есть ссылки в подчиненной таблице
select distinct t1.*
from t1
inner join t2 on t2.t1id = t1.id

И получение строк, на которые нет ссылок в подчиненной таблице
select distinct t1.*
from t1
left join t2 on t2.t1id = t1.id
where t2.id is null


Вобщем пользуйтесь на здоровье, и избегайте не нужной работы серверов

MSSQL : Оптимизация запросов - убираем TOP 1

Иногда бывает необходимо получить только некие "верхние" записи из подчиненной таблицы
Кто-то делает так:
select *
, (select top 1 t2.id from t2 where t1Id = t1.id)
, (select top 1 t2.someData from t2 where t1Id = t1.id)
from t1


Чем плох такой вариант? А плох он следующим.
Мы ориентируемся на некое "верхнее" значение, которое может не относиться в нужной нам последовательности в итоге.
Кроме этого, у нас может возникнуть ситуация когда вызовы "верхнего" значения будут относиться к разным строкам таблицы.
Что тогда будете делать?
Поэтому я предлагаю использовать агрегирующий подзапрос

select *
from t1
inner join (select max(id) id, t1Id from t2 group by t1Id) T2i on t1.id = T2i.t1Id
inner join t2 on t2.id = T2i.id

В большинстве своем мы получим более лучший план запроса, эффективность во времени, предсказуемость (точность) результата.