2015-01-26 80 views
-2

我在我們的應用程序中使用的一個sproc中看到了性能問題。OR WHERE子句會降低sql查詢性能(sql server)

這是一個非常大的問題,我已經縮小到我看到性能問題的部分。

它在where子句中(複製如下)。查詢估計計劃顯示這部分大約需要80%。

邏輯是,@AssignedToIds@AssignedToRoleIds可以爲空,它是空的,那麼我們將拉所有的記錄。 臨時表可以有多行。不勝感激任何幫助提高性能。

#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

爲什麼選擇?爲什麼不加入他們呢? – 2015-01-26 21:52:41

+0

加入將無法使用。這些是有條件的連接。如果變量 - @ - AssignedToIds或 - @ - AssignedToRoleIds具有值,我只需要加入臨時表。 – pmh 2015-01-26 21:56:40

+2

您有頂部x行,但沒有順序。沒有命令你無法知道哪些行將被返回。 – 2015-01-26 22:33:57

回答

0

你可以嘗試添加

option(recompile) 

若要在SQL查詢結束。看看它是否會加快它的速度。

+0

。沒有運氣 – pmh 2015-01-26 21:56:08

+0

我想我們可能需要在這裏查看整個查詢。也許可能你可能需要用一個帶有索引的臨時表的幫助來檢查,以加快速度或某事。儘管如此,很難用那個假設來作出這樣的假設。 – 2015-01-26 21:58:32

+0

感謝您的期待。這是完整的查詢 – pmh 2015-01-26 22:02:34

0

個人有這麼多的條件在這個where子句它將成爲一個噩夢找出性能問題。

如果是我,我會把這個查詢拆分成更小的查詢,以便您正在處理不斷減少的子集。

如得到的只是

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檢查哪裏條款可能是昂貴的。