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 !&#2'),('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 SERVER 查看sql语句性能与执行时间

SQL中多分支If语句的性能(Sql Server 2008)

SQL Server 查询性能异常语句

SQL Server 查询性能异常语句

Sql Server 优化 SQL 查询:如何写出高性能SQL语句

SQL Server:性能问题:WHERE 子句中的 OR 语句替换