我有一张包含一些州的表格。有些状态意味着正在进行的状态,因为其他程序员可能会使用查询来获取它们, 例如“所有正在进行的订单”等。
我创建了一个这样的函数,因为也许正在进行的订单状态稍后会发生变化:
CREATE FUNCTION [dbo].[fn_GetStates]()
RETURNS TABLE
AS
RETURN
SELECT CAST('registered' AS VARCHAR(75)) AS OrderState
UNION ALL
SELECT 'OnBoardModify' OrderState
UNION ALL
SELECT 'OnCanceling' OrderState
UNION ALL
SELECT 'OnSending' OrderState
当我使用此功能时,它比旧查询慢。
旧查询
SELECT *
FROM dbo.Order
WHERE state IN ('OnBoardModify','registered','OnCanceling')
新查询
SELECT *
FROM dbo.Order_MOT
WHERE OMSOrderState IN (
SELECT * FROM [dbo].[fn_GetOpenOrderState]()
)
有什么更好的办法吗?
当我使用表格或函数或...时
在 SQL 查询中使用函数(标量或表值)会破坏可以使用并行性和索引搜索的数据处理集方法,并且需要对表的每一行 (RBAR) 顺序执行该函数。
自 2017 版以来,对优化器(智能查询处理)的改进,尤其是在 FROID 项目(标量 UDF:内对齐)的框架内的改进,允许尽可能将函数的 SQL 重新合并为集合表达式.
如果您的实例是 2019 年或更高版本,您可以通过将 UDF 重新设计为标量函数、重写查询以使用标量函数并检查您的数据库是否处于 2019 年或 2022 年向后兼容模式(具体取决于您的实例)来受益。
否则,请删除此函数并恢复查询中的原始代码。
CREATE FUNCTION [dbo].[fn_GetStates](@state VARCHAR(100))
RETURNS BIT
AS
BEGIN
RETURN CASE WHEN @state IN ('registered', 'OnBoardModify', 'OnCanceling', 'OnSending')
THEN 1
ELSE 0
END
END;
SELECT *
FROM dbo.Order
WHERE [dbo].[fn_GetStates](state) = 1;