Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Типовая проблема LEFT JOIN + "OR"  [new]
NIIIK
Member

Откуда: Россия, Ростовская область, г. Таганрог
Сообщений: 1295
Запрос имеет следующую структуру

select ...
  from tSomeMainTable mt
   left
   join tSomeChildTable ct
     on mt.pk = ct.fkSomeMainTable
   --Some other joins 
 where (mt.isBlaBla = 1 or ct.isBlaBla2 = 1) --(sometimes "ct.pk is null possible in another test case"
     ....


Так вот,
1) если оставить только одно из полей в
mt.isBlaBla = 1 or ct.isBlaBla2 = 1

работает быстро
2) если поменять на INNER join - работает быстро (но соотвественно НЕ правильно)
3) Если делать костыли в духе

- с TOP

with cte as
(
select top 2147483647 
          ...
  from tSomeMainTable mt
   left
   join tSomeChildTable ct
     on mt.pk = ct.fkSomeMainTable
where (mt.isBlaBla = 1 or ct.isBlaBla2 = 1) --(sometimes "ct.pk is null possible in another test case"
)
select ...
  from cte mt
   left
   join tSomeChildTable ct --(it will be necessary later this is why it's used twice)
     on mt.pk = ct.fkSomeMainTable
   --Some other joins 
 where 
     ....


- или "union" оператор


with cte as
(
select top 2147483647 
          mt.*
  from tSomeMainTable mt
   join tSomeChildTable ct
     on mt.pk = ct.fkSomeMainTable
    and ct.isBlaBla2 = 1 
union
select mt.*
  from tSomeMainTable mt
where mt.isBlaBla = 1

)
select ...
  from cte mt
   left
   join tSomeChildTable ct --(it will be necessary later this is why it's used twice)
     on mt.pk = ct.fkSomeMainTable
   --Some other joins 
 where 
     ....



При этом когда смотришь план полного тормозящего запроса - основной COST на Index seek-ах других таблиц.
Выдранные в отдельный запрос две таблицы с первичным условия тоже выполнется быстро.

Какие основные моменты должны быть сделаны при наисании такого кусказа запроса с left join и OR оператором?
5 мар 13, 11:01    [14012735]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
Crimean
Member

Откуда:
Сообщений: 13147
"обычно" при проблемах с OR первое что делают - меняют на UNION. все правильно найдено
5 мар 13, 11:27    [14012956]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
Cygapb-007
Member

Откуда:
Сообщений: 1677
по возможности на UNION ALL :)
5 мар 13, 11:31    [14012973]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
Referee
Member

Откуда:
Сообщений: 151
можно попробовать

select ...
  from tSomeMainTable mt
   left
   join tSomeChildTable ct
     on mt.pk = ct.fkSomeMainTable
       and ct.isBlaBla2 = 1
   --Some other joins 
 where (mt.isBlaBla = 1 or ct.pk is not null)
     ....
5 мар 13, 11:35    [14012995]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
NIIIK
Member

Откуда: Россия, Ростовская область, г. Таганрог
Сообщений: 1295
Cygapb-007
по возможности на UNION ALL :)


не, дублирование может пойти.

Ищу "не костыльные методы".
Но из двух костылей выбрал бы "топ"
5 мар 13, 11:38    [14013017]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
NIIIK
Member

Откуда: Россия, Ростовская область, г. Таганрог
Сообщений: 1295
Referee
можно попробовать

select ...
  from tSomeMainTable mt
   left
   join tSomeChildTable ct
     on mt.pk = ct.fkSomeMainTable
       and ct.isBlaBla2 = 1
   --Some other joins 
 where (mt.isBlaBla = 1 or ct.pk is not null)
     ....


Не получилось,
но запросы не равные
tSomeChildTable ct может ещё использоваться,
хотя это можно было бы обойти ещё одни джойном
5 мар 13, 11:45    [14013078]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
NIIIK
Member

Откуда: Россия, Ростовская область, г. Таганрог
Сообщений: 1295
кстати, запрос с CTE +TOP
работает так же (по плану) как и обычный пока TOP не поставишь.
5 мар 13, 11:46    [14013094]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
Bator
Member

Откуда: Порт пяти морей
Сообщений: 439
NIIIK
Какие основные моменты должны быть сделаны при наисании такого кусказа запроса с left join и OR оператором?

При OR на разные поля не используется индекс, поэтому обычно используют UNION (без ALL)
CTE здесь не обязательно, можно просто
SELECT ... FROM
  (...
   UNION
   ...) as un
WHERE ...

но лучше два раза повторить условие
SELECT ... FROM ... WHERE A=1 AND <SomeWhere1>
UNION
SELECT ... FROM ... WHERE B=1 AND <SomeWhere1>
6 мар 13, 11:15    [14018339]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
NIIIK
Member

Откуда: Россия, Ростовская область, г. Таганрог
Сообщений: 1295
Я в целом переписал запрос (сначала с хинтом, потом один inner заменил на left).

Я думаю кривой план выбирался в том числе и из-затого что одна из таблиц (которая left+условие where обрезала кучу данны) находилась в другой базе того же инстанса.

По факту то план выбирался "правильный" - индекс сики работали.
Но в итоге после "манипуляций" помогал хинт loop к ДРУГОЙ таблице или потом лефт джойн.

а вообще хотелось бы писать оператор " OR " без колхозов с union, зная что они потом работать и будут.
6 мар 13, 11:24    [14018390]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
butwhy?
Guest
первоначальный запрос и запрос с CTE+TOP выдают разные результаты :

declare @mt table( id int)
declare @ct table( mt_id int, id int)

insert @mt values( 1)
insert @ct values( 1, 1), (1, 2)

select mt.id, ct.id as ct_id
from @mt as mt 
   left join @ct as ct
     on mt.id = ct.mt_id
   --Some other joins 
 where ( mt.id = 1 or ct.id = 1) --(sometimes "ct.pk is null possible in another test case"
;

with cte as (
	select top 2147483647 
		mt.id, ct.id as ct_id
	from @mt as mt 
	   left join @ct as ct
		 on mt.id = ct.mt_id
	 where ( mt.id = 1 or ct.id = 1) --(sometimes "ct.pk is null possible in another test case"
) 
select mt.id, ct.id
from cte as mt 
left join @ct as ct
		 on mt.id = ct.mt_id
6 мар 13, 13:13    [14019139]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
butwhy?
первоначальный запрос и запрос с CTE+TOP выдают разные результаты :

declare @mt table( id int)
declare @ct table( mt_id int, id int)

insert @mt values( 1)
insert @ct values( 1, 1), (1, 2)

select mt.id, ct.id as ct_id
from @mt as mt 
   left join @ct as ct
     on mt.id = ct.mt_id
   --Some other joins 
 where ( mt.id = 1 or ct.id = 1) --(sometimes "ct.pk is null possible in another test case"
;

with cte as (
	select top 2147483647 
		mt.id, ct.id as ct_id
	from @mt as mt 
	   left join @ct as ct
		 on mt.id = ct.mt_id
	 where ( mt.id = 1 or ct.id = 1) --(sometimes "ct.pk is null possible in another test case"
) 
select mt.id, ct.id
from cte as mt 
left join @ct as ct
		 on mt.id = ct.mt_id
Дело не в TOP (уберите его, если сомневаетесь).
Первый запрос - один LEFT JOIN + WHERE
Второй запрос - один LEFT JOIN + WHERE + ещё один LEFT JOIN
Уберите из второго запроса LEFT JOIN с CTE - и наслаждайтесь!

И бросайте играть в напёрстки
6 мар 13, 13:31    [14019293]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
NIIIK
Member

Откуда: Россия, Ростовская область, г. Таганрог
Сообщений: 1295
Что-то я туплю
А в чём вопрос/ответ ?!

В общем проблема была в том что left join таблицы из другой базы + where довольно сильно "фильтруют данные", но вплан выполнения срабатывал в последнюю очередь и примерял этот left join + where в последнюю очередь по очень большому набору строк. Хотя при этом "жолгий джойн" был с Index Seek -ами (только количество строк большое).

оба колхозных метода вынуждали выполнить сначала ту часть запроса, которая "ограничивала данные раньше".

В итоге задача решена заменой inner join yf left outer join, причём РОДИТЕЛЬСКОЙ таблицы (по факту обязательной).
6 мар 13, 14:22    [14019668]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
TJ001
Member

Откуда: от верблюда
Сообщений: 428
тоже из-за этого в тупике :'(
может у меня все неправильно - подскажите как правильно...

t4 - маленькая таблица, ~100 записей, все остальные тяжелые
select
t1.*,t4.f1,t5.f1
from
t1

join f6
on t1.f2 =f6.t1

left join t2
on t2.f1 = t1.f2

left join t3
on t3.f1 = t1.f2

left join t4 as t4
on t4.f1 = t2.f3

left join t4 as t5
on t5.f1 = t3.f3

where
f6...

в этом случае индекс используется, но, понятное дело - таблица t4 подключается дважды...

если сделать так
select
t1.*,t4.f1
from
t1

join f6
on t1.f2 =f6.t1

left join t2
on t2.f1 = t1.f2

left join t3
on t3.f1 = t1.f2

left join t4
on t4.f1 = t2.f3 or t4.f1 = t3.f3

where
f6...

перестает работать индекс, выполняется Clustered Index Scan
но запрос отрабатывает быстрее, видимо из-за небольшой таблицы t4

как воспользоваться индексом во 2м варианте? или это вообще иначе делается?
17 апр 13, 10:47    [14190923]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
Мистер Хенки
Member

Откуда: канализация
Сообщений: 6615
попробуйте union all
select
t1.*,t4.f1
from
t1

join f6
on t1.f2 =f6.t1

left join t2
on t2.f1 = t1.f2

left join t3
on t3.f1 = t1.f2

left join t4
on t4.f1 = t2.f3 

where
f6...
union all
select
t1.*,t4.f1
from
t1

join f6
on t1.f2 =f6.t1

left join t2
on t2.f1 = t1.f2

left join t3
on t3.f1 = t1.f2

left join t4
on  t4.f1 = t3.f3

where
f6...
17 апр 13, 10:52    [14190952]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
NIIIK
Member

Откуда: Россия, Ростовская область, г. Таганрог
Сообщений: 1295
не помню чем решал, но ещё попробуйте поиграться с хинтами

а-ля
left
loop --merge, hash
join

Потом в уловиях попробуйте именно задизейблить индекс каким-нить костылём а-ля

on t1.field1 + 0 = t2.field1
17 апр 13, 11:13    [14191149]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
TJ001
Member

Откуда: от верблюда
Сообщений: 428
Мистер Хенки,

да, работает, спасибо

но запрос удвоился в размерах, он и раньше -то был не маленький...
а если подключится еще несколько таблиц, для которых нужно будет такое сопоставление, то запрос станет просто космическим :'(
17 апр 13, 11:25    [14191260]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
TJ001
Member

Откуда: от верблюда
Сообщений: 428
NIIIK,

зачем же отключать индекс? ведь именно он мне и нужен...
17 апр 13, 11:26    [14191275]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
TJ001
а если подключится еще несколько таблиц, для которых нужно будет такое сопоставление, то запрос станет просто космическим :'(

вам жалко букв ?
17 апр 13, 11:28    [14191296]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
TJ001
Member

Откуда: от верблюда
Сообщений: 428
Maxx,

нет не жалко...


чёрт, ордеры и топы перестали работать
17 апр 13, 11:30    [14191312]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
TJ001,
select...
UNION
select....
UNION
select....
order by
17 апр 13, 11:33    [14191333]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
TJ001
Member

Откуда: от верблюда
Сообщений: 428
Maxx,

да, я уже починил, но все равно спасибо за небезразличие! :)
17 апр 13, 11:36    [14191360]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
Мистер Хенки
Member

Откуда: канализация
Сообщений: 6615
Maxx
TJ001
а если подключится еще несколько таблиц, для которых нужно будет такое сопоставление, то запрос станет просто космическим :'(

вам жалко букв ?

индусам платят за количество строк, а тут еще и код улучшается
17 апр 13, 12:18    [14191749]     Ответить | Цитировать Сообщить модератору
 Re: Типовая проблема LEFT JOIN + "OR"  [new]
TJ001
Member

Откуда: от верблюда
Сообщений: 428
Мистер Хенки,

ну мыж не индусы
17 апр 13, 12:58    [14192191]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить