2015-01-26 4 views
-2

Я вижу проблему производительности в одном из sproc, который мы используем в нашем приложении.ИЛИ в выражении WHERE замедляется производительность SQL-запросов (sql-сервер)

Это очень большой sproc, и я сузил его до той части, где я вижу проблему с производительностью.

Это предложение where (скопировано ниже). План оценки запросов показывает, что эта часть занимает около 80%.

Логика в том, что @AssignedToIds и @AssignedToRoleIds могут быть пустыми, это пустые, тогда мы потянем все записи. Таблицы Temp могут иметь несколько строк. Любая помощь по повышению производительности очень ценится.

#AssignedTo и #AssignedToRole - это временные таблицы.

#AssignedTo имеет только одно значение в таблице и #AssignedToRole пуст

SQL: -

SELECT DISTINCT TOP 2000 t.Member_Party_PartyId AS Member_Party_PartyId 
FROM Task t 
WHERE t.IsDeleted = 0 
    AND (
     t.DueDate >= @DueStart 
     OR @DueStart IS NULL 
     ) 
    AND (
     t.DueDate <= @DueEnd 
     OR @DueEnd IS NULL 
     ) 
    AND (
     (
      @FilterType = 'MyPatients' 
      AND t.AssignedUserId = @UserId 
      ) 
     OR @FilterType != 'MyPatients' 
     ) 
    AND (@FilterType != 'MyRole') 
    AND (
     (
      @FilterType = 'MyGroup' 
      AND t.AssignedUserId IN (
       SELECT PartyId 
       FROM #OrgMembers 
       ) 
      ) 
     OR @FilterType != 'MyGroup' 
     ) 
    AND (
     (
      @FilterType = 'Custom' 
      AND vpad.Provider IN (
       SELECT PartyId 
       FROM #OrgMembers 
       ) 
      ) 
     OR @FilterType != 'Custom' 
     ) 
    AND (
     (
      @ActiveCase = 1 
      AND cases.CaseId IS NOT NULL 
      ) 
     OR @ActiveCase = 0 
     ) 
    AND (
     t.TaskStatusId IN (
      SELECT TaskStatusId 
      FROM #TaskStatus 
      ) 
     ) 
    AND (
     t.TaskCategoryId IN (
      SELECT TaskCategoryId 
      FROM #TaskCategory 
      ) 
     OR @TaskCategoryIds IS NULL 
     ) 
    AND (
     t.TaskPriorityId IN (
      SELECT TaskPriorityId 
      FROM #TaskPriority 
      ) 
     OR @TaskPriorityIds IS NULL 
     ) 
    AND (
     rm.RegistryId IN (
      SELECT RegistryId 
      FROM #Registry 
      ) 
     OR @RegistryIds IS NULL 
     ) 
    AND (
     (
      fg.CareMeasureId IN (
       SELECT CareMeasureId 
       FROM #CareMeasure 
       ) 
      AND exclusion.MemberId IS NULL 
      ) 
     OR @CareMeasureIds IS NULL 
     ) 
    AND (
     vpad.OrganizationId IN (
      SELECT OrganizationId 
      FROM #Organization 
      ) 
     OR (
      SELECT count(OrganizationId) 
      FROM #Organization 
      ) = 0 
     ) 
    AND (
     vpad.Provider IN (
      SELECT ProviderId 
      FROM #Provider 
      ) 
     OR @ProviderIds IS NULL 
     ) 
    AND (
     cases.CaseTypeId IN (
      SELECT CaseTypeId 
      FROM #CaseType 
      ) 
     OR @CaseIds IS NULL 
     ) 
    AND 
    --(case when @AssignedToIds Is Not Null And then t.AssignedUserId in (select AssignedToId from #AssignedTo)) 
    (
     (
      t.AssignedUserId IN (
       SELECT AssignedToId 
       FROM #AssignedTo 
       ) 
      OR (
       @AssignedToIds IS NULL 
       AND @AssignedToRoleIds IS NULL 
       ) 
      ) 
     OR (
      t.AssignedRoleId IN (
       SELECT AssignedRoleId 
       FROM #AssignedToRole 
       ) 
      OR (
       @AssignedToRoleIds IS NULL 
       AND @AssignedToIds IS NULL 
       ) 
      ) 
     ) 
    AND (
     vpad.OrganizationId IN (
      SELECT OrganizationId 
      FROM #UserOrgs 
      ) 
     OR (
      (
       SELECT count(OrganizationId) 
       FROM #UserOrgs 
       ) = 0 
      ) 
     OR (@RoleType <> 'Manager') 
     ) 
    AND (
     (
      mhp.MemberHealthPlanTypeId IN (
       SELECT HealthPlanId 
       FROM #HealthPlan 
       ) 
      AND hpds.HierarchyOrder IS NOT NULL 
      ) 
     OR @HealthPlanIds IS NULL 
     ) 
OPTION (RECOMPILE); 
+3

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

+0

Регистрация не будет работать. Это условные объединения. Мне нужно только присоединить временные таблицы, если переменные - @ - AssignedToIds или - @ - AssignedToRoleIds имеют значения. – pmh

+2

У вас есть вершины x строк, но нет порядка.Без какого-либо заказа у вас нет способа узнать, какие строки будут возвращены. –

ответ

0

Вы могли бы попробовать добавить

option(recompile) 

К концу этого SQL запроса. Посмотрите, скоро ли это ускорится.

+0

уже добавлен. Не повезло – pmh

+0

Думаю, нам может понадобиться весь запрос здесь. Возможно, вам, возможно, придется выполнить эту проверку с помощью таблицы temp с индексом, чтобы ускорить ее или что-то в этом роде. Трудно сделать это предположение только с тем, где утверждение. –

+0

Спасибо, что посмотрели. Вот полный запрос – pmh

0

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

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

например, получить результаты только

INSERT INTO myWorkingTable (some columns here....) 
SELECT 
    DISTINCT TOP 2000 
    t.Member_Party_PartyId AS Member_Party_PartyId 
FROM 
    Task t 
WHERE 
    t.IsDeleted = 0 

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

например. так, например, ваша логика:

(
t.DueDate >= @DueStart 
OR 
    @DueStart IS NULL 
) 

может быть может быть выполнена

IF(@DueStart IS NOT NULL) 
BEGIN 
--LEAVE ONLY THOSE ITEMS WHERE @DueStart >= dueDate 
DELETE FROM myWorkingTable WHERE t.DueDate < @DueStart 
END 

Так другие условия, как это за пределами «основного» запроса.

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

Я знаю, что это не прямо ответить на вопрос, но с чем-то это монолитным это будет практически невозможно для кого-то, чтобы просто сказать: «Ваша проблема с этим битом»

Хотя делать NULL Проверки в пределах где предложение может быть дорогостоящим.

Смежные вопросы