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

Откуда:
Сообщений: 36
select dc.Id as DcId,
(case when dc.Conclusion = 0 then N'Не пройден' else N'Пройден' end) as Result,
isnull(batch.StatusId, 0) as BatchStatusId
from dc.DiagnosticCards as dc inner join
tr.RegDocuments as rd on dc.RegDocumentId = rd.Id inner join
dic.TransportModels as tm on rd.ModelId = tm.Id inner join
dic.TransportBrands as tb on tm.BrandId = tb.Id inner join
dic.TransportCategories as tcat on rd.CategoryId = tcat.Id inner join
dic.TransportColors as tc on rd.ColorId = tc.Id inner join
dic.InspectionCenters as ic on dc.InspectionCenterId = ic.Id inner join
dic.InspectionTypes as it on dc.InspectionTypeId = it.Id inner join
dic.Regions as reg on dc.InspectionRegionId = reg.Id inner join
tic.IssuedTicketDetails as itd on dc.Id = itd.DiagnosticCardId left join
tic.IssuedTickets as ist on itd.TicketId = ist.Id left join
tic.IcTicketRanges as itr on ist.RangeId = itr.Id left join
tic.TiTicketRanges as ttr on itr.RangeId = ttr.Id left join
tic.TicketRanges as tr on ttr.RangeId = tr.Id left outer join
dbo.BatchDc as bdc on bdc.Id = (select top(1) Id from dbo.BatchDc as bdci where bdci.DcId = dc.Id order by bdci.Id desc) left join
dbo.Batch as batch on batch.BatchNumber = bdc.BatchNumber join
dbo.SystemParams as sp on sp.Id = 8
where (bdc.Id is null)
or (batch.StatusId = 3 and datediff(day, batch.BatchDateCreated, getdate()) > 1)
or (batch.StatusId = 4 and datediff(day, batch.BatchDateCreated, getdate()) > 5)
or (batch.StatusId = 5)
or (bdc.StatusId = 4)
or (isnull(dc.ModifiedDate, 0) != isnull(bdc.DcDateUpdated, 0))
or (isnull(tb.ModifiedDate, 0) != isnull(bdc.BrandDateUpdated, 0))
or (isnull(tm.ModifiedDate, 0) != isnull(bdc.ModelDateUpdated, 0))
or (isnull(tcat.ModifiedDate, 0) != isnull(bdc.CategoryDateUpdated, 0))
or (isnull(tc.ModifiedDate, 0) != isnull(bdc.ColorDateUpdated, 0))
or (isnull(ic.ModifiedDate, 0) != isnull(bdc.InspCenterDateUpdated, 0))
or (isnull(rd.ModifiedDate, 0) != isnull(bdc.RegDocumentsDateUpdated, 0))

Можно ли перезаписать этот запрос, чтобы набор возвращаемых данных был те же, но время выполнение запроса был быстрее? Если можно, то как?
5 фев 13, 12:52    [13877119]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
aleks2
Guest
Куды ж те стока OR в where?
5 фев 13, 13:14    [13877310]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
Crimean
Member

Откуда:
Сообщений: 13148
2 Amankeldi

- проверить планы на отсутствие convert для полей входящих в индексы. если есть - причесать типы данных с включением головы

- проверить, чтобы join были по уникальным наборам полей. если нет - переосмыслить

- вот это, возможно, заменить на outer apply, что даст 1 обращение к dbo.BatchDc для получения всех ее полей:

outer join
dbo.BatchDc as bdc on bdc.Id = (select top(1) Id from dbo.BatchDc as bdci where bdci.DcId = dc.Id order by bdci.Id desc)

- такое число OR + параметризация в WHERE намекают как минимум на option( recompile ) для получения оптимальных планов для разного числа определенных / разных значений параметров

- вот это:

or (batch.StatusId = 3 and datediff(day, batch.BatchDateCreated, getdate()) > 1)
or (batch.StatusId = 4 and datediff(day, batch.BatchDateCreated, getdate()) > 5)

"инвертировать" как условие для в смысле превратить в "batch.BatchDateCreated > " - проще же сделать dateadd( getdate())

- вообще по возможности сократить "константную" часть WHERE, полностью зависящую от входных параметров, сиквел это делает хреново (весь этот мусор будет всегда вычисляться)

- вот этот ужас переосмыслить и переписать без isnull. ибо "or" + "!=" + применение функции к полю = куча-море "вычислений после", а нам нужны "сравнения до"

or (isnull(dc.ModifiedDate, 0) != isnull(bdc.DcDateUpdated, 0))
or (isnull(tb.ModifiedDate, 0) != isnull(bdc.BrandDateUpdated, 0))
or (isnull(tm.ModifiedDate, 0) != isnull(bdc.ModelDateUpdated, 0))
or (isnull(tcat.ModifiedDate, 0) != isnull(bdc.CategoryDateUpdated, 0))
or (isnull(tc.ModifiedDate, 0) != isnull(bdc.ColorDateUpdated, 0))
or (isnull(ic.ModifiedDate, 0) != isnull(bdc.InspCenterDateUpdated, 0))
or (isnull(rd.ModifiedDate, 0) != isnull(bdc.RegDocumentsDateUpdated, 0))
5 фев 13, 14:14    [13877868]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Crimean
or (isnull(dc.ModifiedDate, 0) != isnull(bdc.DcDateUpdated, 0))
or (isnull(tb.ModifiedDate, 0) != isnull(bdc.BrandDateUpdated, 0))
or (isnull(tm.ModifiedDate, 0) != isnull(bdc.ModelDateUpdated, 0))
or (isnull(tcat.ModifiedDate, 0) != isnull(bdc.CategoryDateUpdated, 0))
or (isnull(tc.ModifiedDate, 0) != isnull(bdc.ColorDateUpdated, 0))
or (isnull(ic.ModifiedDate, 0) != isnull(bdc.InspCenterDateUpdated, 0))
or (isnull(rd.ModifiedDate, 0) != isnull(bdc.RegDocumentsDateUpdated, 0))
AND NOT EXISTS
(
 SELECT dc.ModifiedDate,tb.ModifiedDate,tm.ModifiedDate,tcat.ModifiedDate,tc.ModifiedDate,ic.ModifiedDate,rd.ModifiedDate
 INTERSECT
 SELECT bdc.DcDateUpdated,bdc.BrandDateUpdated,bdc.ModelDateUpdated,bdc.CategoryDateUpdated,bdc.ColorDateUpdated,bdc.InspCenterDateUpdated,bdc.RegDocumentsDateUpdated
)
5 фев 13, 14:32    [13878015]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
Гость333
Member

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

А с какой целью делается "join dbo.SystemParams"? Вроде бы нигде эта таблица не используется.

Crimean
вообще по возможности сократить "константную" часть WHERE, полностью зависящую от входных параметров

А что в этом запросе является входными параметрами? Вроде ничего похожего на параметры в тексте запроса не видно.
5 фев 13, 14:37    [13878055]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
Crimean
Member

Откуда:
Сообщений: 13148
Гость333
А что в этом запросе является входными параметрами? Вроде ничего похожего на параметры в тексте запроса не видно.


точно. провтыкал
recompile убираем - он "мимо кассы"
outer apply оставляем - лишнее обращение уйдет
intersect пробуем - возможно будет "интереснее", с нуловостью он вроде корректен
дальше - смотреть на таблички (размеры, селективности), возможно поможет что-то типа option( force order ), если оптимизатор запутается (а с него станется - запрос не самый простой) в порядке применения соединений
5 фев 13, 15:05    [13878245]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
Amankeldi
Member

Откуда:
Сообщений: 36
Огромное спасибо за советы! Попробую....
5 фев 13, 16:37    [13878993]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
iap
Member

Откуда: Москва
Сообщений: 47001
Только вот ещё: надо подобрать порядок JOINов, если FORCE ORDER.
Да и без него, вообще-то, тоже.
Очень всё зависит при таком количестве этих самых JOINов...
Надо постараться в начало переставить по возможности маленькие таблицы и далее по возрастанию.
Ну и не напортачить с порядком INNER/LEFT, естественно.
5 фев 13, 16:53    [13879158]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация запроса  [new]
Crimean
Member

Откуда:
Сообщений: 13148
и еще добавлю - сама по себе выборка "безперспективная" ибо шансов особо нету у сервера ее эффективно выполнить при текущей "постановке задачи"
пример
скажем, когда есть табличка Table1 с полем Column1 и с индексом на это поля - тогда запрос вида
select * from Table1 where Column1 = @Value1
понятно как выполнять - взять кусочек данных по индексу

а у вас же все условно сводится к ситуации табличка Table1 с полями Column1, Column2 и запрос вида
select * from Table1 where Column1 = Column2
и как серверу это "оптимизировать"? правильно - никак - только все просканить и сравнить
5 фев 13, 17:02    [13879254]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить