ahmed_sa Ответов: 1

Почему этот запрос очень медленный, когда вы добавляете эти 4 строки ?


Я работаю на SQL server 2012 у меня есть проблема с запросом

запрос очень медленный я тестирую его слишком много времени я понял что проблема в этих строках


потому что все запросы занимают 50 минут, чтобы увидеть результат

когда я удаляю строки выше запрос занимает 7 минут

Итак, как решить эту проблему, как блок жирным шрифтом ниже

SELECT F.CompanyID , 
 COUNT(CASE WHEN FI.FamilyLevel= 1 THEN  p.PartID  END )  Count_Yes_InForeCast ,  

 COUNT(CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 THEN  p.PartID END )  Count_No_InForeCast ,
------------------block that start problem
 COUNT(CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 AND PF.IntroductionDate IS NULL THEN  p.PartID END )  Count_No_InTroudctionNULLForeCast ,

 COUNT(CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 AND PF.IntroductionDate IS not NULL THEN  p.PartID END )  Count_No_InTroudctionNotNULLForeCast ,

 COUNT(CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 AND PF.IntroductionDate IS not NULL AND isnull(PF.Comment,'') LIKE '%appro%'  THEN  PF.PartID END )  Count_No_InTroudctionNotNULLAPPForeCast ,

 COUNT(CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 AND PF.IntroductionDate IS not NULL AND isnull(PF.Comment,'') NOT LIKE '%appro%'   THEN  PF.PartID END )  Count_No_InTroudctionNotNULLNoAPPForeCast ,
-----------end block
 COUNT(DISTINCT CASE WHEN FI.FamilyLevel= 1 THEN  FI.FamilyID  END )  CountFamily_Yes_InForeCast ,  
 COUNT(DISTINCT CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 THEN  FI.FamilyID END )  CountFamily_No_InForeCast into #ForecastTotal

   FROM Parts.FamilyIntroductionDate FI WITH(NoLock) INNER JOIN  parts.Nop_PartsFamily  F  ON F.PartFamilyID =fi.FamilyID

INNER JOIN parts.Nop_Part P WITH(NoLock) ON p.PartsFamilyID=f.PartFamilyID
LEFT OUTER  JOIN  parts.PartsForecast PF WITH(NoLock)  ON pf.PartID=p.PartID 
GROUP BY   F.CompanyID

План исполнения

Запрос плана выполнения[^]

Что я уже пробовал:

COUNT(CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 AND PF.IntroductionDate IS NULL THEN  p.PartID END )  Count_No_InTroudctionNULLForeCast ,

 COUNT(CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 AND PF.IntroductionDate IS not NULL THEN  p.PartID END )  Count_No_InTroudctionNotNULLForeCast ,

 COUNT(CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 AND PF.IntroductionDate IS not NULL AND isnull(PF.Comment,'') LIKE '%appro%'  THEN  PF.PartID END )  Count_No_InTroudctionNotNULLAPPForeCast ,

 COUNT(CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 AND PF.IntroductionDate IS not NULL AND isnull(PF.Comment,'') NOT LIKE '%appro%'   THEN  PF.PartID END )  Count_No_InTroudctionNotNULLNoAPPForeCast

Herman<T>.Instance

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

ahmed_sa

он находится по этой ссылке
https://www.brentozar.com/pastetheplan/?id=Hyss6rlLL

ZurdoDev

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

1 Ответов

Рейтинг:
8

Maciej Los

Что касается меня... слишком много COUNT(CASE WHEN ...)

Я бы выделил данные в меньшее количество полей, чем ваше, а затем свернул бы данные (или подсчитал данные), как я показал вам здесь: Как отдельное поле partdone к тексту, да или нет, или нуль, в зависимости от положения ?[^].

Улучшенный запрос может выглядеть следующим образом:

SELECT CompanyID, InForeCast, COUNT(InForeCast) AS CountInForeCast, InTroudctionForeCast, COUNT(InTroudctionForeCast) AS CountInTroudctionForeCast, InTroudctionNoAPPForeCast, COUNT(InTroudctionNoAPPForeCast) AS CountInTroudctionNoAPPForeCast 
FROM(
  SELECT F.CompanyID, ISNULL(FI.FamilyLevel, 0)=1 AS InForeCast,
    InTroudctionForeCast = CASE 
        WHEN ISNULL(FI.FamilyLevel,0)= 0 THEN ISDATE(PF.IntroductionDate) --returns 1 - if true/0 - if false
    END,
    InTroudctionNoAPPForeCast =  CASE 
        WHEN ISNULL(FI.FamilyLevel,0)= 0 AND ISDATE(PF.IntroductionDate)=1 THEN  ISNULL(PF.Comment,'') LIKE '%appro%' --returns true/false
    END
-- below lines are repeated!
--,
-- COUNT(DISTINCT CASE WHEN FI.FamilyLevel= 1 THEN  FI.FamilyID  END )  CountFamily_Yes_InForeCast ,  
-- COUNT(DISTINCT CASE WHEN ISNULL(FI.FamilyLevel,0)= 0 THEN  FI.FamilyID END )  CountFamily_No_InForeCast into #ForecastTotal
FROM Parts.FamilyIntroductionDate FI WITH(NoLock)
    INNER JOIN  parts.Nop_PartsFamily  F  ON F.PartFamilyID =fi.FamilyID
    INNER JOIN parts.Nop_Part P WITH(NoLock) ON p.PartsFamilyID=f.PartFamilyID
    LEFT OUTER  JOIN  parts.PartsForecast PF WITH(NoLock)  ON pf.PartID=p.PartID 
GROUP BY F.CompanyID
) AS T
GROUP BY CompanyID, InForeCast, InTroudctionForeCast, InTroudctionNoAPPForeCast


Примечание: у меня нет доступа к вашим данным, поэтому вышеприведенный запрос, возможно, потребуется улучшить.