Производительность SQL-запроса с оператором case - PullRequest
1 голос
/ 22 апреля 2019

У меня есть простой выбор, который работает очень медленно и сузил его до одного конкретного where оператора.

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

Для этого конкретного примера. декларация выглядит следующим образом: Declare @lastInvOnly as int = 0

Оператор задачи where следует и работает около 20 секунд:

 and ird.inventorydate = case when @lastinvonly=0 then  --get the last reported inventory in respect to the specified parameter
        (select max(ird2.inventorydate)    from irdate ird2
                where ird2.ris =r.ris and ird2.generateddata!='g'and ird2.inventorydate <= @inventorydate)
            end

удаление case заставляет его работать за 1 секунду, что является ОГРОМНОЙ разницей. Я не могу понять почему.

and ird.inventorydate = 
            (select max(ird2.inventorydate)    from irdate ird2
                    where ird2.ris =r.ris and ird2.generateddata!='g'and ird2.inventorydate <= @inventorydate)

Ответы [ 2 ]

1 голос
/ 22 апреля 2019

Это почти наверняка должна быть производная таблица, и вы должны присоединиться к ней.Суб-выборки, как правило, имеют низкую производительность, а при условном использовании - еще хуже.Попробуйте вместо этого:

INNER JOIN (
   select
       ris
      ,max(inventorydate) AS [MaxInvDate]
   from irdate
   where s and generateddata!='g'
   and inventorydate <= @inventorydate
   GROUP BY ris
) AS MaxInvDate ON MaxInvDate.ris=r.ris
and ird.inventorydate=MaxInvDate.MaxInvDate
and @lastinvonly=0

Я не уверен на 100%, это логически работает со всем запросом, поскольку ваш вопрос содержит только небольшую часть.

0 голосов
/ 23 апреля 2019

Я не могу сказать наверняка, не увидев план выполнения, но ветка в вашем фильтре, вероятно, является причиной проблем с производительностью. Теоретически, оптимизатор может взять версию без регистра и применить оптимизацию, которая преобразует подзапрос в вашем фильтре в соединение; при добавлении оператора case эта оптимизация больше невозможна, и подзапрос выполняется для каждой строки. Можно изменить код, чтобы помочь оптимизатору, что-то вроде этого должно работать:

outer apply (
    select max(ird2.inventorydate) as maxinventorydate
    from irdate ird2
    where ird2.ris = r.ris
      and ird2.generateddata <> 'g'
      and ird2.inventorydate <= @inventorydate
      and @lastinvonly = 0
) as ird2
where ird.inventorydate = ird2.maxinventorydate
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...