我正在创建一个 DWH,在其中将数据加载到临时数据库中,并在将它们加载到最终数据库之前应用我在数据上创建的所有 udf。
- 源数据库:Oracle
- 目标数据库:SQL Server
- ETL 流程:SSIS 包
我没有在暂存过程中处理任何内容以实现快速加载。
问题:当数据本身处于暂存状态时应用任何 udf 是否更快,或者应该在将数据加载到最终数据库时完成。
下面的facility_cd是一个float值,我将它传递给函数emr_get_code_Description来获取相应的描述。从中获取描述的表位于最终数据库中。 udf_replace_special_char
是一个简单的函数,它用 NULL 替换一些特殊字符。
LTRIM(RTRIM([Dest_DWH].[dbo].udf_replace_special_char([Dest_DWH].[dbo].[emr_get_code_Description](Stg_ap.Facility_cd))))
一般来说,更好的做法应该是什么?我是否应该在暂存中更新它,然后在所有转换为最终数据库后加载数据。
函数定义:
功能1:
USE [PROD_DWH]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER function [dbo].[emr_get_code_Description](@cv int)
returns varchar(80)
as begin
-- Returns the code value display
declare @ret varchar(80)
select @ret = cv.DESCRIPTION
from PROD_DWH.DBO.table cv
where cv.code_value = @cv
and cv.active_ind = 1
return isnull(@ret, 0)
end;
功能2:
USE [PROD_DWH]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER function [dbo].[udf_replace_special_char](@var varchar(1000))
returns varchar(1000)
as begin
-- Returns the code value display
declare @return_var varchar(1000)
set @return_var = @var
set @return_var = replace(@return_var,CHAR(13),'')
set @return_var = replace(@return_var,CHAR(10),'')
set @return_var = replace(@return_var,CHAR(09),'')
set @return_var = replace(@return_var,CHAR(34),CHAR(39))
return isnull(@return_var, 0)
end;
最佳答案
首先,正如 @Nick.McDermaid 在评论中提到的:最佳实践是避免使用用户定义的函数。有许多链接包含有关函数对查询性能影响的信息。
- Removing Function Calls for Better Performance in SQL Server
- Performance Considerations of User-Defined Functions in SQL Server 2012
- Are SQL Server Functions Dragging Your Query Down?
- T-SQL Best Practices - Don't Use Scalar Value Functions in Column List or WHERE Clauses
这些问题没有理想的答案,这与您正在处理的案例有关,但我可以提供一些您可以考虑的提示:
- 首先,如果您使用 SSIS 将数据导入到临时表中,请尝试使用 SSIS 数据流组件(例如派生列转换、查找)替换用户定义的函数,这样可以增强数据导入的性能。里>
- 如果无法用 SSIS 组件替换 UDF:如果您正在高速收集数据到数据湖(暂存级别),然后在需要时加载数据,则在将数据导入到暂存表时最好避免使用函数.
- 如果您需要保证从临时表加载数据时的高速性,请在第一个数据导入阶段使用该功能。
- 如果第一个数据导入阶段(到临时表)和第二个阶段(从临时表)不是在同一台计算机上执行,则最好在性能更高的计算机上执行函数。
- 如果函数包含一些查找等操作,请尝试用连接替换它们。
...
更新 1
在问题中发布函数后,您可以将函数 2 替换为 SSIS 包中的派生列转换:
ISNULL([Column]) ? "" : REPLACE(REPLACE(REPLACE(REPLACE([Column],CHAR(10),""),CHAR(13),""),CHAR(09),""),CHAR(34),CHAR(39))
您还可以将函数 1 替换为 SSIS 包中的查找转换或 SQL 查询中的 LEFT JOIN。
关于sql - 何时在 SQL Server 数据仓库中使用用户定义的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54282348/