T-SQL中替换函数的性能问题

时间:2010-02-18 19:44:39

标签: tsql

我有一个正在处理的大表,几乎所有列都需要使用replace语句来删除单引号和双引号。代码如下所示:

SET QUOTED_IDENTIFIER ON

Update dbo.transactions set transaction_name1 = Replace(transaction_name1,'''','')
Update dbo.transactions set transaction_name2 = Replace(transaction_name2,'''','')
Update dbo.transactions set transaction_name3 = Replace(transaction_name3,'''','')
Update dbo.transactions set transaction_name4 = Replace(transaction_name4,'''','')
Update dbo.transactions set transaction_name5 = Replace(transaction_name5,'''','')

我没有在表上放置一个索引,因为我不确定哪个列有什么好处,我正在更新几乎所有的列。如果我按主键对表格进行排序会有助于提高性能吗?

那时语句已经运行了2个多小时没有错误消息,并且想知道是否有解决这个性能问题的解决方案,除了通常更多的硬件更改?如果有人可以就如何提高脚本性能提出建议。

干杯, 彼得

3 个答案:

答案 0 :(得分:4)

您可以将其设为一个UPDATE语句:

UPDATE transactions SET
  transaction_name1 = Replace(transaction_name1,'''',''),
  transaction_name2 = Replace(transaction_name2,'''','')
  ... (and so on)

这可能会使性能提高近5倍。


编辑:

由于这是一个巨大的数据集(90MM行)上的一个镜头,我建议添加一个where子句并批量运行。

如果您的交易有主键,请在其上对更新进行分区,一次执行500k。

在具有显式事务的循环中执行此操作,以使日志使用保持最小:

DECLARE @BaseID INT, @BatchSize INT
SELECT @BaseID = MAX(YourKey), @BatchSize = 500000 FROM transactions

WHILE @BaseID > 0 BEGIN

  PRINT 'Updating from ' + CAST(@BaseID AS VARCHAR(20))

  -- perform update
  UPDATE transactions SET
    transaction_name1 = Replace(transaction_name1,'''',''),
    transaction_name2 = Replace(transaction_name2,'''','')
    -- ... (and so on)
  WHERE YourKey BETWEEN @BaseID - @BatchSize AND @BaseID

  SET @BaseID = @BaseID - @BatchSize - 1

END

另一个注意事项:

如果报价不得出现在您的数据中,您可以创建一个check constraint来阻止它们。这是最后的努力,因为任何尝试将它们放入的应用程序都需要处理数据库异常,但它保持您的数据清洁。这样的事情可能会这样做:

ALTER TABLE transactions
  ADD CONSTRAINT CK_NoQuotes CHECK(
    CHARINDEX('''',transaction_name1)=0 AND
    CHARINDEX('''',transaction_name2)=0 AND
    -- and so on...
  )

答案 1 :(得分:2)

您可以将这些语句组合起来,这可能会更快一些:

SET QUOTED_IDENTIFIER ON

UPDATE dbo.transactions
SET transaction_name1 = REPLACE(transaction_name1,'''',''),
    transaction_name2 = REPLACE(transaction_name2,'''',''),
    transaction_name3 = REPLACE(transaction_name3,'''',''),
    transaction_name4 = REPLACE(transaction_name4,'''',''),
    transaction_name5 = REPLACE(transaction_name5,'''','')

另外,查看估计的执行计划。 它可能会为您提供有关如何优化数据库/查询的有用建议(它是SQL Management Studio按钮栏中的一个小方块按钮)。

答案 2 :(得分:1)

您可能只尝试将其设为一个UPDATE并仅更新需要它的行:

UPDATE dbo.transactions
SET transaction_name1 = REPLACE(transaction_name1,'''',''),
    transaction_name2 = REPLACE(transaction_name2,'''',''),
    transaction_name3 = REPLACE(transaction_name3,'''',''),
    transaction_name4 = REPLACE(transaction_name4,'''',''),
    transaction_name5 = REPLACE(transaction_name5,'''','')
WHERE 
    CHARINDEX('''',transaction_name1)>0
    OR CHARINDEX('''',transaction_name2)>0
    OR CHARINDEX('''',transaction_name3)>0
    OR CHARINDEX('''',transaction_name4)>0
    OR CHARINDEX('''',transaction_name5)>0