Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Долго выполняется запрос с использованием Left Join  [new]
Арчи05
Member

Откуда:
Сообщений: 158
Всем привет.

Написал такой запрос

автор
select t1.id, t1.kol1, t2.kol2, t3.kol3 from
(select id, kol1 from kolic where <условие>) t1
left join
(select id, kol2 from kolic where <условие>) t2 on t1.id=t2.id
left join
(select id, kol3 from kolic where <условие>) t3 on t1.id=t3.id


Проблема в том, что если я в самом верхнем select перечисляю поля из всех объединенных таблиц,
то запрос выполняется очень долго и не дожидаясь его останавливаю.

Но если оставить всё как есть, а изменить только самый верхний select, то все работает

автор
select t1.id, t1.kol1 from
(select id, kol1 from kolic where <условие>) t1
left join
(select id, kol2 from kolic where <условие>) t2 on t1.id=t2.id
left join
(select id, kol3 from kolic where <условие>) t3 on t1.id=t3.id


Не могу понять в чем дело...
12 мар 12, 12:58    [12230874]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Гавриленко Сергей Алексеевич
Member

Откуда:
Сообщений: 37254
Арчи05
Не могу понять в чем дело...
Это нормально, когда разные запросы выполняются по-разному.
12 мар 12, 12:59    [12230883]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Гузы
Guest
Арчи05,

М.б.
select id, case when <условие 1> then kol end as kol1,... from kolic 
будет быстрее?
12 мар 12, 13:18    [12231027]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
select t1.id, t1.kol1, t2.kol2, t3.kol3
from kolic t1
left join kolic t2 on <условие t2> and t1.id=t2.id
left join kolic t3 on <условие t3> and t1.id=t3.id
where <условие t1>
Так разве не понятнее выглядит?
12 мар 12, 13:24    [12231078]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Арчи05
Member

Откуда:
Сообщений: 158
iap
select t1.id, t1.kol1, t2.kol2, t3.kol3
from kolic t1
left join kolic t2 on <условие t2> and t1.id=t2.id
left join kolic t3 on <условие t3> and t1.id=t3.id
where <условие t1>
Так разве не понятнее выглядит?


А что это ускорит запрос?

Гавриленко Сергей Алексеевич
Арчи05
Не могу понять в чем дело...
Это нормально, когда разные запросы выполняются по-разному.


Как понять?
Объясни пожалуйста.

Если говорить о времени работы одного запроса то каждый запрос по отдельности работает быстро (каждый примерно по 2 минута).
12 мар 12, 14:37    [12231846]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
iljy
Member

Откуда:
Сообщений: 8711
Арчи05
Гавриленко Сергей Алексеевич
пропущено...
Это нормально, когда разные запросы выполняются по-разному.


Как понять?
Объясни пожалуйста.

Если говорить о времени работы одного запроса то каждый запрос по отдельности работает быстро (каждый примерно по 2 минута).

Понять буквально. Планы этих 2х запросов сравните, сразу все понятно станет. Хотя вообще запрос реально странный, правильно Гузы заметил.
12 мар 12, 14:42    [12231890]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Арчи05
Member

Откуда:
Сообщений: 158
iljy
Арчи05
пропущено...


Как понять?
Объясни пожалуйста.

Если говорить о времени работы одного запроса то каждый запрос по отдельности работает быстро (каждый примерно по 2 минута).

Понять буквально. Планы этих 2х запросов сравните, сразу все понятно станет. Хотя вообще запрос реально странный, правильно Гузы заметил.


Я вкратце описал проблему, т.е. упростил ситуацию
12 мар 12, 14:46    [12231927]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Glory
Member

Откуда:
Сообщений: 104751
Арчи05
Как понять?
Объясни пожалуйста.

У вас разные запросы. Потому что они возвращают разные результаты.
А разные запросы не должны работать одинаково

А ваш запрос по-моему вообще преобразуется к виду

select t1.id, t1.kol1, 
case when <условие> then kol1 end as kol2,
case when <условие> then kol1 end as kol3
from kolic t1 
where <условие> 
12 мар 12, 14:46    [12231930]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Гузы
Guest
Glory
...А ваш запрос по-моему вообще преобразуется к виду
select t1.id, t1.kol1, 
case when <условие1> then kol1 end as kol2,
case when <условие2> then kol1 end as kol3
from kolic t1 
where <условие3> 

Вообще-то см. выше, но уважаемый не учел:
 (<условие1>  and  <условие2> and <условие3> )= false ?

И нужно еще как-то завернуть:
select id, sum(kol1), sum(kol2), sum(kol3) from
(селект. который выше) tt
group by id
12 мар 12, 15:02    [12232099]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Арчи05
Member

Откуда:
Сообщений: 158
Тогда я приведу весь текст запроса, чтоб стало понятней (возможно)

DECLARE @pstart char(6), @pend char(6);
SET @pstart = '201108'
SET @pend = '201201'


select tall.glpu, tall.kol_kd, tall.kolpos, tall.sumv_oms from 
(select uslugi.glpu, sum(uslugi.ed_col) as kol_kd, 
isnull(sum(case when uslugi.ed_col=0 and left(uslugi.code_usl,1)='9' then uslugi.tarif*uslugi.kol_usl*0.76 when uslugi.ed_col=0 and left(uslugi.code_usl,1)!='9' then uslugi.kol_usl end),0000000000000000.00) as kolpos,
sum(case when uslugi.stand='false' then uslugi.sumv_usl 
	 when uslugi.stand='true' then 
		  case when uslugi.ed_col>0 then uslugi.sumv_usl-uslugi.tarif 
			   when uslugi.ed_col=0 and left(uslugi.code_usl,1)='9' then uslugi.sumv_usl-(uslugi.tarif*uslugi.kol_usl*0.76*s_lpu.dostup) 
			   when uslugi.ed_col=0 and (left(uslugi.code_usl,2)='00' or uslugi.sumv_usl=0) then 0 
			   else uslugi.sumv_usl-(s_lpu.dostup*kol_usl)
		  end
	end) as sumv_oms
from uslugi 
inner join s_lpu on uslugi.code_mo=s_lpu.mcod
inner join straxs on rtrim(uslugi.id_sch)+rtrim(uslugi.idstrax)=rtrim(straxs.id_sch)+rtrim(straxs.idstrax)
inner join (select distinct pacient.id_sch, pacient.spolis, pacient.npolis, pacient.novor, pacient.smo from  pacient) pac1
on rtrim(straxs.id_sch)+rtrim(straxs.spolis)+rtrim(straxs.npolis)+cast(straxs.novor as char(1))=rtrim(pac1.id_sch)+rtrim(pac1.spolis)+rtrim(pac1.npolis)+ltrim(rtrim(pac1.novor))
where left(straxs.id_sch,6) between @pstart and @pend and rtrim(pac1.smo) in ('05501','05701')
group by uslugi.glpu) tall
left join 
(select uslugi.glpu, sum(uslugi.ed_col) as m_kol_kd, 
isnull(sum(case when uslugi.ed_col=0 and left(uslugi.code_usl,1)='9' then uslugi.tarif*uslugi.kol_usl*0.76 when uslugi.ed_col=0 and left(uslugi.code_usl,1)!='9' then uslugi.kol_usl end),0000000000000000.00) as m_kolpos,
sum(case when uslugi.stand='false' then uslugi.sumv_usl 
	 when uslugi.stand='true' then 
		  case when uslugi.ed_col>0 then uslugi.sumv_usl-uslugi.tarif 
			   when uslugi.ed_col=0 and left(uslugi.code_usl,1)='9' then uslugi.sumv_usl-(uslugi.tarif*uslugi.kol_usl*0.76*s_lpu.dostup) 
			   when uslugi.ed_col=0 and (left(uslugi.code_usl,2)='00' or uslugi.sumv_usl=0) then 0 
			   else uslugi.sumv_usl-(s_lpu.dostup*kol_usl)
		  end
	end) as m_sumv_oms
from uslugi 
inner join s_lpu on uslugi.code_mo=s_lpu.mcod
inner join straxs on rtrim(uslugi.id_sch)+rtrim(uslugi.idstrax)=rtrim(straxs.id_sch)+rtrim(straxs.idstrax)
inner join (select distinct pacient.id_sch, pacient.spolis, pacient.npolis, pacient.novor, pacient.smo from  pacient) pac1
on rtrim(straxs.id_sch)+rtrim(straxs.spolis)+rtrim(straxs.npolis)+cast(straxs.novor as char(1))=rtrim(pac1.id_sch)+rtrim(pac1.spolis)+rtrim(pac1.npolis)+ltrim(rtrim(pac1.novor))
where left(straxs.id_sch,6) between @pstart and @pend and rtrim(pac1.smo)='05501'
group by uslugi.glpu) tmaks 
on tall.glpu=tmaks.glpu
left join 
(select uslugi.glpu, sum(uslugi.ed_col) as s_kol_kd, 
isnull(sum(case when uslugi.ed_col=0 and left(uslugi.code_usl,1)='9' then uslugi.tarif*uslugi.kol_usl*0.76 when uslugi.ed_col=0 and left(uslugi.code_usl,1)!='9' then uslugi.kol_usl end),0000000000000000.00) as s_kolpos,
sum(case when uslugi.stand='false' then uslugi.sumv_usl 
	 when uslugi.stand='true' then 
		  case when uslugi.ed_col>0 then uslugi.sumv_usl-uslugi.tarif 
			   when uslugi.ed_col=0 and left(uslugi.code_usl,1)='9' then uslugi.sumv_usl-(uslugi.tarif*uslugi.kol_usl*0.76*s_lpu.dostup) 
			   when uslugi.ed_col=0 and (left(uslugi.code_usl,2)='00' or uslugi.sumv_usl=0) then 0 
			   else uslugi.sumv_usl-(s_lpu.dostup*kol_usl)
		  end
	end) as s_sumv_oms
from uslugi 
inner join s_lpu on uslugi.code_mo=s_lpu.mcod
inner join straxs on rtrim(uslugi.id_sch)+rtrim(uslugi.idstrax)=rtrim(straxs.id_sch)+rtrim(straxs.idstrax)
inner join (select distinct pacient.id_sch, pacient.spolis, pacient.npolis, pacient.novor, pacient.smo from  pacient) pac1
on rtrim(straxs.id_sch)+rtrim(straxs.spolis)+rtrim(straxs.npolis)+cast(straxs.novor as char(1))=rtrim(pac1.id_sch)+rtrim(pac1.spolis)+rtrim(pac1.npolis)+ltrim(rtrim(pac1.novor))
where left(straxs.id_sch,6) between @pstart and @pend and rtrim(pac1.smo)='05701'
group by uslugi.glpu) tsov 
on tall.glpu=tsov.glpu
13 мар 12, 09:30    [12236354]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Арчи05
Member

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

select tall.glpu, tall.kol_kd, tall.kolpos, tall.sumv_oms, tmaksl.m_kol_kd, tmaks.m_kolpos, tmaks.m_sumv_oms, tsov.s_kol_kd, tsov.s_kolpos, tsov.s_sumv_oms from 
(select uslugi.glpu, sum(uslugi.ed_col) as kol_kd,
......


То запрос выполняется долго ... на 25 минутах я останавливаю не дожидаясь завершения
13 мар 12, 09:35    [12236374]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Арчи05
Member

Откуда:
Сообщений: 158
DECLARE @pstart char(6), @pend char(6);
SET @pstart = '201108'
SET @pend = '201201'


select tall.glpu, tall.kol_kd, tall.kolpos, tall.sumv_oms,
tmaks.m_kol_kd, tmaks.m_kolpos, tmaks.m_sumv_oms, 
tsov.s_kol_kd, tsov.s_kolpos, tsov.s_sumv_oms from 
(select uslugi.glpu, kol_kd, kolpos, sumv_oms from uslugi) tall
left join 
(select uslugi.glpu, m_kol_kd, m_kolpos, m_sumv_oms from uslugi) tmaks 
on tall.glpu=tmaks.glpu
left join 
(select uslugi.glpu, s_kol_kd, s_kolpos, s_sumv_oms from uslugi) tsov 
on tall.glpu=tsov.glpu


Упростил чуть для понимания сути.
13 мар 12, 10:07    [12236536]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
Арчи05
Всем привет.

Написал такой запрос

автор
select t1.id, t1.kol1, t2.kol2, t3.kol3 from
(select id, kol1 from kolic where <условие>) t1
left join
(select id, kol2 from kolic where <условие>) t2 on t1.id=t2.id
left join
(select id, kol3 from kolic where <условие>) t3 on t1.id=t3.id


Проблема в том, что если я в самом верхнем select перечисляю поля из всех объединенных таблиц,
то запрос выполняется очень долго и не дожидаясь его останавливаю.

Но если оставить всё как есть, а изменить только самый верхний select, то все работает

автор
select t1.id, t1.kol1 from
(select id, kol1 from kolic where <условие>) t1
left join
(select id, kol2 from kolic where <условие>) t2 on t1.id=t2.id
left join
(select id, kol3 from kolic where <условие>) t3 on t1.id=t3.id


Не могу понять в чем дело...

1) Как уже было сказано, разные запросы выполняются по-разному.
2) Чтобы вам помогли оптимизировать запрос нужно прикладывать план выполнения, желательно конечно реальный. Аттачем .sqlplan
3) Или разбейте запрос на 3 отдельных запроса с временными таблицами и с большой вероятностью это решит проблему.
13 мар 12, 10:21    [12236625]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Арчи05
Member

Откуда:
Сообщений: 158
Mind,

Да дело в том, до этого подобные запросы проходили на УРА, а сейчас проблема, не могу понять в чем дело.

Создавать временные таблицы как-то не хотелось, некрасиво получается
13 мар 12, 10:50    [12236859]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
SanyL
Member

Откуда: Москва
Сообщений: 4540
Арчи05
Mind,

Да дело в том, до этого подобные запросы проходили на УРА, а сейчас проблема, не могу понять в чем дело.

Создавать временные таблицы как-то не хотелось, некрасиво получается


Вам же сказали... давайте смотреть планы выполнения...

То что они работали на ура = замечательно! Сейчас не работают... В чем причина? Например, изменилась гистограмма распределение данных = изменился план, давно не обновлялись статистики = изменился план. А как оно в реальности ни кто не знает - может у вас там дисковая подсистема умирает...
13 мар 12, 10:58    [12236924]     Ответить | Цитировать Сообщить модератору
 Re: Долго выполняется запрос с использованием Left Join  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
Арчи05
Mind,

Да дело в том, до этого подобные запросы проходили на УРА, а сейчас проблема, не могу понять в чем дело.

Подобные - это какие? Где перечислены поля только из первого подзапроса? Ну да, в этом случае из 2-х других подзапросов сервер интересует только будут ли ID по которым происходит соединение уникальны или нет и все. Он наверняка не выполняет эти подзапросы целиком, смысла нет, вот вам и разница.

Арчи05
Создавать временные таблицы как-то не хотелось, некрасиво получается

У вас есть такие варианты:
1) Переписать под временные таблицы и не отправлять ваш запрос на конкурс красоты, попутно можно прочитать скажем вот эту статью, о том почему и когда нужно разбивать большие запросы http://sqlcat.com/sqlcat/b/technicalnotes/archive/2011/10/21/when-to-break-down-complex-queries.aspx
2) Продолжать рассказывать про то что раньше работало, а сечас не работает, надеясь на то что заработает само.
3) Погадать на кофейной гуще, чтобы понять что нужно исправить
4) Помолиться Богу, Аллаху или другому всевышнему.
5) Ну и как самый бесперспективный вариант - посмотреть на планы выполнения и выложить их на форум.


А вот это безобразие никогда красиво работать не будет:
on rtrim(straxs.id_sch)+rtrim(straxs.spolis)+rtrim(straxs.npolis)+cast(straxs.novor as char(1))=rtrim(pac1.id_sch)+rtrim(pac1.spolis)+rtrim(pac1.npolis)+ltrim(rtrim(pac1.novor))
тут у вас джойн по конкатенированным полям, что наверняка напрочь убивает возможность сделать правильные оценки и как следствие построить оптимальный план.


where left(straxs.id_sch,6) between @pstart and @pend and rtrim(pac1.smo) in ('05501','05701')
ну а это уже классика, поиск по индексу не возможен.

Переделывайте базу или добавляйте CALCULATED PERSISTED колонки или делайте через временные таблицы.
13 мар 12, 20:34    [12242695]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить