SQL Server 更新语句性能
Posted
技术标签:
【中文标题】SQL Server 更新语句性能【英文标题】:SQL Server update statement performance 【发布时间】:2017-08-12 11:48:40 【问题描述】:我在优化 SQL 查询以进行数据清理时遇到问题。
事实上,我有一个表,它是多个特殊字符和单词的一种参考。我们就叫它ABNORMAL(ID,PATTERN)
我还有另一个表 INDIVIDUALS
包含一个列 (NAME
),我想通过删除表 ABNORMAL
中存在的所有字符来清理它。
目前,我已尝试使用更新语句,但不确定是否有更好的方法。
接近一
使用 while 循环将包含来自 ABNORMALS
的所有字符替换为空白 '' 并使用内置的 REPLACE
进行一次更新
DECLARE @REPLACE_EXPRESSION nvarchar(max) ='REPLACE(NAME,'''','''')'
DECLARE @i int = 1
DECLARE @nbr int = (SELECT COUNT(*) FROM ABNORMAL)
-- CURRENT_CHARAC
DECLARE @CURRENT_CHARAC nvarchar(max)
-- NEW REPLACE EXPRESSION TO IMBRICATE INTO THE REPLACE EXPRESSION VARIABLE
DECLARE @CURR_REP NVARCHAR(max)
-- STRING TO BUILD AN SQL QUERY CONTAINING THE REPLACE EXPRESSION
DECLARE @UPDATE_QUERY nvarchar(max)
WHILE @i < @nbr
BEGIN
SELECT @CURRENT_CHARAC=PATTERN FROM CLEANSING_STG_PRISM_FRA_REF_UNSIGNIFICANT_VALUES WHERE ID_PATTERN=@i ;
SET @REPLACE_EXPRESSION = REPLACE(@REPLACE_EXPRESSION ,'NAME','REPLACE(NAME,'+''''+@CURRENT_CHARAC+''''+','''')')
set @i=@i+1
END
SET @UPDATE_QUERY = 'UPDATE INDIVIDUAL SET NAME ='+ @REPLACE_EXPRESSION
EXEC sp_executesql @UPDATE_QUERY
方法二
使用 while 循环选择每个异常字符,并使用包含要删除的字符的替换进行更新:
DECLARE @i int = 1
DECLARE @nbr int = (SELECT COUNT(*) FROM ABNORMAL)
-- CURRENT_CHARAC
DECLARE @CURRENT_CHARAC nvarchar(max)
-- STRING TO BUILD AN SQL QUERY CONTAINING THE REPLACE EXPRESSION
DECLARE @UPDATE_QUERY nvarchar(max)
WHILE @i < @nbr
BEGIN
SELECT @CURRENT_CHARAC=PATTERN FROM CLEANSING_STG_PRISM_FRA_REF_UNSIGNIFICANT_VALUES WHERE ID_PATTERN=@i ;
UPDATE INDIVIDUAL
SET NAME = REPLACE(NAME,@CURRENT_CHARAC,'')
SET @i=@i+1
END
我已经针对 200 万条记录测试了这两种方法,我发现第一种方法比第二种方法更快。我想知道您是否已经尝试过类似的和新的(更好的)想法。
【问题讨论】:
【参考方案1】:如果您使用SQL Server 2017
,您可以使用TRANSLATE
并避免使用动态SQL:
SELECT i.*
, REPLACE(TRANSLATE(i.NAME, f, REPLICATE('!', s.l)), '!', '') AS cleansed
FROM INDIVIDUALS i
OUTER APPLY (SELECT STRING_AGG(PATTERN, '') AS f
,LEN(STRING_AGG(PATTERN,'')) AS l
FROM ABNORMAL) AS s
DBFiddle Demo
无论如何,第一种方法更好,因为你只做一个UPDATE
,第二种方法你一次删除一个字符(所以你会有多个UPDATE
)。
我还将使用这两种方法跟踪事务日志的增长。
【讨论】:
您好,感谢您的反馈。不幸的是,我使用的是 sql server 2016。但是您能否澄清一下“跟踪事务日志”是什么意思?这如何优化我的查询?【参考方案2】:如果要清理的字符不多,那么这个技巧可能会奏效。
基本上,您构建 1 个大更新语句,用要删除的字符替换表中的每个值。
示例代码:
测试数据(使用临时表)
create table #ABNORMAL_CHARACTERS (id int identity(1,1), chr varchar(30));
insert into #ABNORMAL_CHARACTERS (chr) values ('!'),('&'),('#');
create table #INDIVIDUAL (id int identity(1,1), name varchar(30));
insert into #INDIVIDUAL (name) values ('test 1 &'),('test !'),('test 3');
代码:
declare @FieldName varchar(30) = 'name';
declare @Replaces varchar(max) = @FieldName;
declare @UpdateSQL varchar(max);
select @Replaces = concat('replace('+@Replaces+', ', ''''+chr+''','''')') from #ABNORMAL_CHARACTERS order by id;
set @UpdateSQL = 'update #INDIVIDUAL
set name = '+@Replaces + '
where exists (select 1 from #ABNORMAL_CHARACTERS where charindex(chr,name)>0)';
exec (@UpdateSQL);
select * from #INDIVIDUAL;
一个测试here on rextester
如果您有一个可以进行正则表达式替换的 UDF。 例如here 那么@Replaces 变量可以简化为只有 1 个 RegexReplace 函数和一个模式。
【讨论】:
以上是关于SQL Server 更新语句性能的主要内容,如果未能解决你的问题,请参考以下文章
SQL中多分支If语句的性能(Sql Server 2008)