使用文本更新varchar列的最快方法

时间:2011-03-17 00:55:39

标签: sql-server tsql sql-server-2008 string

我在一栏中有以下内容:

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

我需要将这些列更新为:

MindWorks.Client.Accounts

我最初想过使用字符串函数来更新它们(LEFT,SUBSTR等),但是有没有替代或更好的方法来更新列中的文本以插入文本?

我使用的是SQL Server 2008,无法使用CLR集成。

2 个答案:

答案 0 :(得分:10)

这是一个关于“最快”的问题,因此下面提供了时间

测试设置,表格>> 100万行

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 vs Replace vs SubString

效果摘要 - STUFF> SUBSTRING> REPLACE

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

SQL Server解析和编译时间:
         CPU时间= 0 ms,经过时间= 3 ms       表'MetaDataServe'。扫描计数1,逻辑读取55402,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0       
       SQL Server执行时间:
         CPU时间= 10094 ms,经过时间= 10808 ms          CPU时间= 10250 ms,经过时间= 10896 ms。

(2次来自多次执行以显示可变性,它非常低,因此可以认为时间精确到3%以内)

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

SQL Server解析和编译时间:
         CPU时间= 3 ms,经过时间= 3 ms       表'MetaDataServe'。扫描计数1,逻辑读取55402,物理读取0,预读读取159,lob逻辑读取0,lob物理读取0,lob预读读取0       
       SQL Server执行时间:
         CPU时间= 20469 ms,经过时间= 21238 ms。

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

SQL Server解析和编译时间:
         CPU时间= 0 ms,经过时间= 1 ms       表'MetaDataServe'。扫描计数1,逻辑读取55402,物理读取0,预读读取3,lob逻辑读取0,lob物理读取0,lob预读读取0       
       SQL Server执行时间:
         CPU时间= 11219 ms,经过时间= 12030 ms          CPU时间= 11531 ms,经过时间= 12148 ms。

固定号码与PATINDEX对比CHARINDEX

(固定位置版本已在上面给出)
效果摘要 - 已修复> (PATINDEX = CHARINDEX)
PATINDEX与CHARINDEX之间似乎没有实质性差异

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

SQL Server解析和编译时间:
         CPU时间= 0 ms,经过时间= 2 ms       表'MetaDataServe'。扫描计数1,逻辑读取55400,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0       
       SQL Server执行时间:
         CPU时间= 15218 ms,经过时间= 16167 ms。

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

SQL Server解析和编译时间:
         CPU时间= 0 ms,经过时间= 3 ms       表'MetaDataServe'。扫描计数1,逻辑读取55402,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0       
       SQL Server执行时间:
         CPU时间= 15469 ms,经过时间= 16353 ms。

注意:

  • 根据您的需要,上面给出的所有更新声明都可以(有一两个调整)
  • 在每次测试之前,删除整个表并重新创建以防止缓存问题

小心!

即使STUFF速度更快,您也可能遇到棘手的情况。如果您的数据包含

"MindWorksNoDot"

您使用

进行更新
update MetaDataServe set vc = STUFF(vc, CHARINDEX('.',vc), 0, '.Client')

你最终得到了NULL!因为当CHARINDEX找不到点时,STUFF的第二个参数为零(0)会导致整个字符串转到 NULL

最终词汇

为了安全性和可靠性,鉴于它只比STUFF方法慢33%,我只想使用REPLACE语句,即

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

答案 1 :(得分:3)

使用STUFF command

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 command

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可能更灵活。只是取决于你的需求。