самый быстрый способ обновить столбец varchar с текстом - PullRequest
5 голосов
/ 17 марта 2011

У меня есть следующее в столбце:

MetaDataServe
-------------
MindWorks.Accounts
MindWorks.Transactions
MindWorks.Commissions
...

Мне нужно обновить эти столбцы в виде:

MindWorks.Client.Accounts

Сначала я думал об использовании строковых функций для их обновления (LEFT, SUBSTR и т. Д.), Но есть ли альтернативный или лучший способ обновления текста в столбце для вставки текста?

Я использую SQL Server 2008 и не могу использовать интеграцию CLR.

Ответы [ 2 ]

10 голосов
/ 17 марта 2011

Это вопрос о "самом быстром", поэтому время приведено ниже

Тестовая настройка, таблица с> 1 млн. Строк

create table MetaDataServe (id int identity primary key, vc varchar(max));

insert MetaDataServe values
('MindWorks.Accounts'),
('MindWorks.Transactions'),
('MindWorks.Commissions');

insert MetaDataServe
select vc
from MetaDataServe, master..spt_values a, master..spt_values b
where b.number between 1 and 30
-- (1090110 row(s) affected)

Материал против Замены против Подстроки

Сводка производительности - STUFF> SUBSTRING> REPLACE

update MetaDataServe set vc = STUFF(vc, 9, 0, '.Client')

Время разбора и компиляции SQL Server:
Время ЦП = 0 мс, прошедшее время = 3 мс.
Таблица «MetaDataServe». Сканирование 1, логическое чтение 55402, физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0.

Время выполнения SQL Server:
Время процессора = 10094 мс, прошедшее время = 10808 мс.
Время ЦП = 10250 мс, прошедшее время = 10896 мс.

(2 раза от нескольких исполнений, чтобы показать изменчивость, она довольно низкая, поэтому время можно считать точным с точностью до 3%)

update MetaDataServe set vc = REPLACE(vc, '.', '.Client.')

Разбор SQL Server и время компиляции:
Время ЦП = 3 мс, прошедшее время = 3 мс.
Таблица «MetaDataServe». Сканирование 1, логическое чтение 55402, физическое чтение 0, чтение с опережением 159, логическое чтение 1, физическое чтение 1, чтение с опережением 0.

Время выполнения SQL Server:
Время ЦП = 20469 мс, прошедшее время = 21238 мс.

update MetaDataServe set vc = 'MindWorks.Client.' + SUBSTRING(vc, 11, 100)

Разбор SQL Server и время компиляции:
Время ЦП = 0 мс, прошедшее время = 1 мс.
Таблица «MetaDataServe». Сканирование 1, логическое чтение 55402, физическое чтение 0, чтение с опережением 3, чтение логического объекта 0, чтение с физического объекта 0, чтение с опережением 0.

Время выполнения SQL Server:
Время ЦП = 11219 мс, прошедшее время = 12030 мс.
Время ЦП = 11531 мс, прошедшее время = 12148 мс.

Фиксированный номер против PATINDEX против CHARINDEX

(версия с фиксированным положением уже указана выше)
Сводка производительности - ИСПРАВЛЕНО> (PATINDEX = CHARINDEX)
По-видимому, между PATINDEX и CHARINDEX нет существенной разницы

update MetaDataServe set vc = STUFF(vc, PATINDEX('%.%',vc), 0, '.Client')

Разбор SQL Server и время компиляции:
Время ЦП = 0 мс, прошедшее время = 2 мс.
Таблица «MetaDataServe». Сканирование 1, логическое чтение 55400, физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0.

Время выполнения SQL Server:
Время ЦП = 15218 мс, прошедшее время = 16167 мс.

update MetaDataServe set vc = STUFF(vc, CHARINDEX('.',vc), 0, '.Client')

Разбор SQL Server и время компиляции:
Время ЦП = 0 мс, прошедшее время = 3 мс.
Таблица «MetaDataServe». Сканирование 1, логическое чтение 55402, физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0.

Время выполнения SQL Server:
Время ЦП = 15469 мс, прошедшее время = 16353 мс.

Примечания:

  • Все приведенные выше операторы обновления будут работать (с твиком или двумя) в зависимости от ваших потребностей
  • Перед каждым тестом вся таблица удаляется и воссоздается для предотвращения проблем с кэшированием.

ВНИМАНИЕ!

Несмотря на то, что STUFF быстрее, вы можете попасть в сложные ситуации. Если ваши данные содержат

"MindWorksNoDot"

А вы обновляете с помощью

update MetaDataServe set vc = STUFF(vc, CHARINDEX('.',vc), 0, '.Client')

В итоге вы получите NULL! Потому что, когда CHARINDEX не может найти точку, второй параметр STUFF, равный нулю (0), заставляет всю строку переходить к NULL .

ЗАКЛЮЧИТЕЛЬНЫЕ СЛОВА

Для обеспечения безопасности и надежности, поскольку он только на 33% медленнее, чем подход STUFF, я бы просто использовал оператор REPLACE, т.е.

update MetaDataServe set vc = REPLACE(vc, '.', '.Client.')
3 голосов
/ 17 марта 2011

Использование команды STUFF :

WITH sample AS (
  SELECT 'MindWorks.Accounts' AS col
  UNION ALL
  SELECT 'MindWorks.Transactions'
  UNION ALL
  SELECT 'MindWorks.Commissions')
SELECT s.col,
       STUFF(s.col, CHARINDEX('.', s.col), 1, '.Client.') AS col2
  FROM sample s

Использование команды REPLACE :

WITH sample AS (
  SELECT 'MindWorks.Accounts' AS col
  UNION ALL
  SELECT 'MindWorks.Transactions'
  UNION ALL
  SELECT 'MindWorks.Commissions')
SELECT s.col,
       REPLACE(s.col, '.', '.Client.') AS col2
  FROM sample s

Выход:

col                      col2
--------------------------------------------------------
MindWorks.Accounts       MindWorks.Client.Accounts
MindWorks.Transactions   MindWorks.Client.Transactions
MindWorks.Commissions    MindWorks.Client.Commissions

Заключение

Из двух, STUFF, вероятно, будет более гибким.Просто зависит от ваших потребностей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...