我在我们的应用程序中使用的一个sproc中看到了性能问题。
这是一个非常大的问题,我已将其缩小到我看到性能问题的部分。
它位于where子句中(复制如下)。查询估算计划显示该部分约占80%。
逻辑是@AssignedToIds
和@AssignedToRoleIds
可以为null,它为null然后我们将拉出所有记录。
临时表可以有多行。非常感谢任何有关提高性能的帮助。
#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);
答案 0 :(得分:0)
您可以尝试添加
option(recompile)
到那个SQL查询的结尾。看看是否加快了一点。
答案 1 :(得分: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
所以像这样的其他条件可以在&#34; main&#34;之外执行。查询。
然后,您最终可以运行执行计划来检查完整查询,然后应用计划建议的任何建议索引。
我知道它并没有直接回答这个问题,但是对于这个单片的东西来说,几乎不可能只是说'#34;你的问题就是这个问题&#34;
尽管在where子句中执行NULL检查可能成本很高。