Проблемы производительности с функцией замены в T-SQL - PullRequest
1 голос
/ 18 февраля 2010

У меня есть большая таблица, над которой я работаю, и для почти всех столбцов мне нужно использовать оператор замены для удаления одинарных и двойных кавычек. Код выглядит так:

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,'''','')

Я не поместил индекс в таблицу, так как не был уверен, какой именно столбец будет полезным, поскольку я обновляю почти все столбцы. Если бы я отсортировал таблицу asc по первичному ключу, это помогло бы повысить производительность?

После этого операторы работали более 2 часов без сообщений об ошибках и задавались вопросом, есть ли решение этой проблемы с производительностью, помимо обычных дополнительных аппаратных изменений? Если кто-то может посоветовать способы повышения производительности скрипта.

Ура, Питер

Ответы [ 3 ]

4 голосов
/ 18 февраля 2010

Вы можете сделать это одним оператором UPDATE:

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

Это, вероятно, улучшит производительность, если приблизится к коэффициенту, равному 5.


Edit:

Поскольку это одна вещь в огромном наборе данных (90MM строк), я предлагаю добавить предложение where и запускать его партиями.

Если у ваших транзакций есть первичный ключ, разделите обновления на нем, выполнив, возможно, 500 тыс. За один раз.

Делайте это в цикле с явными транзакциями, чтобы свести использование журнала к минимуму:

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

Другое примечание:

Если кавычки не должны появляться в ваших данных, вы можете создать проверочное ограничение , чтобы не допустить их. Это последнее усилие, так как любое приложение, пытающееся поместить их, должно будет обработать исключение базы данных, но оно сохранит ваши данные в чистоте. Нечто подобное может сделать это:

ALTER TABLE transactions
  ADD CONSTRAINT CK_NoQuotes CHECK(
    CHARINDEX('''',transaction_name1)=0 AND
    CHARINDEX('''',transaction_name2)=0 AND
    -- and so on...
  )
2 голосов
/ 18 февраля 2010

Вы можете комбинировать операторы, которые могут быть немного быстрее:

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).

1 голос
/ 18 февраля 2010

Вы можете попробовать сделать только одно ОБНОВЛЕНИЕ и обновить только те строки, которые в этом нуждаются:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...