【发布时间】:2020-10-22 17:03:13
【问题描述】:
我有以下存储过程(在 MS SQL 中):
ALTER PROCEDURE [dbo].[proc_GetWorksWithEngineerVisits3]
@sTextSearch nvarchar(255) = NULL,
@bCompleteFlag bit = NULL,
@dExpectedStartDateTime datetime = NULL,
@dExpectedEndDateTime datetime = NULL,
@sResponsible_UserIDs nvarchar(255) = NULL,
@bEnableTextSearchFilter bit = false,
@bEnableCompleteFlagFilter bit = false,
@bEnableExpectedDateTimeRangeFilter bit = false,
@bEnableResponsible_UserIDFilter bit = false
AS
SELECT *
FROM dbo.vwWorksWithEngineerVisits
WHERE
--TextSearch Filter Start
(sCustomer LIKE CASE
WHEN @bEnableTextSearchFilter = 1
THEN '%' + @sTextSearch + '%'
ELSE sCustomer
END
OR
sSite LIKE CASE
WHEN @bEnableTextSearchFilter = 1
THEN '%' + @sTextSearch + '%'
ELSE sSite
END
OR
sCallID LIKE CASE
WHEN @bEnableTextSearchFilter = 1
THEN '%' + @sTextSearch + '%'
ELSE sCallID
END)
--TextSearch Filter End
AND
--Complete Filter Start
bIsComplete = CASE
WHEN @bEnableCompleteFlagFilter = 1
THEN @bCompleteFlag
ELSE bIsComplete
END
--Complete Filter End
AND
--Expected DateTime Range Filter Start
dExpectedStartDateTime >= CASE
WHEN @bEnableExpectedDateTimeRangeFilter = 1
THEN @dExpectedStartDateTime
ELSE dExpectedStartDateTime
END
AND
dExpectedEndDateTime <=
CASE
WHEN @bEnableExpectedDateTimeRangeFilter = 1
THEN @dExpectedEndDateTime
ELSE dExpectedEndDateTime
END
----Expected DateTime Range Filter End
AND
--Responsible_UserID Filter Start
lResponsible_UserID in (
CASE
WHEN @bEnableResponsible_UserIDFilter = 0
THEN lResponsible_UserID
ELSE (SELECT Value FROM dbo.CSVToList(@sResponsible_UserIDs) AS CSVToList_1)
END
)
--Responsible_UserID Filter End
ORDER BY dExpectedEndDateTime
输出很好,但速度很慢(仅 5000 行需要 15 秒)直接执行 dbo.vwWorksWithEngineerVisits 需要 1 秒相同的数字。执行 SP 时,我将所有启用标志设置为 0。
DECLARE @return_value int
EXEC @return_value = [dbo].[proc_GetWorksWithEngineerVisits3]
@sTextSearch = NULL,
@bCompleteFlag = False,
@dExpectedStartDateTime = N'01/01/1969',
@dExpectedEndDateTime = N'01/01/2021',
@sResponsible_UserIDs = NULL,
@bEnableTextSearchFilter = 0,
@bEnableCompleteFlagFilter = 0,
@bEnableExpectedDateTimeRangeFilter = 0,
@bEnableResponsible_UserIDFilter = 0
SELECT 'Return Value' = @return_value
如果设置了相应的标志,我希望能够只过滤一列。我可能只检查主参数中的 NULL 并减少参数,但我认为它不会改变我遇到的问题。
前 4 个 Case 过滤器非常基本,当我将剩下的最后 3 个注释掉时,性能/结果是即时的。一旦我将最后 3 个中的一个添加回组合中,事情就会像上面一样变慢。使这些不同的是它们执行“>=”或“in”,而不仅仅是“=”或“like”。我注意到的另一件事是,当我更改以下内容时:
lResponsible_UserID in (
CASE
WHEN @bEnableResponsible_UserIDFilter = 0
THEN lResponsible_UserID
ELSE (SELECT Value FROM dbo.CSVToList(@sResponsible_UserIDs) AS CSVToList_1)
END
到
lResponsible_UserID in (
CASE
WHEN @bEnableResponsible_UserIDFilter = 0
THEN lResponsible_UserID
ELSE lResponsible_UserID
END
这也将速度提高到 1 秒。当标志始终为 0 时,更改语句的 else 部分有何不同,所以永远不应该运行?
我需要这些过滤器,而且我需要它们是动态的。有多种运算符类型(包括以函数为目标的 IN)。有没有办法重构这个存储过程以获得相同的结果(它确实有效),但以一种更可选的方式?
如果我在帖子中遗漏了某些内容,我深表歉意,如果指出,我会进行编辑。
谢谢
【问题讨论】:
标签: sql sql-server stored-procedures case query-performance