【问题标题】:fastest way to update varchar column with text用文本更新 varchar 列的最快方法
【发布时间】:2011-03-17 00:55:38
【问题描述】:

我在一列中有以下内容:

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

我需要将这些列更新为:

MindWorks.Client.Accounts

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

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

【问题讨论】:

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


    【解决方案1】:

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

    测试设置,超过 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 毫秒,经过的时间 = 3 毫秒。
    表“元数据服务”。扫描计数 1,逻辑读取 55402,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

    SQL Server 执行时间:
    CPU 时间 = 10094 毫秒,运行时间 = 10808 毫秒。
    CPU 时间 = 10250 毫秒,经过时间 = 10896 毫秒。

    (2次是多次执行,以显示变异性,非常低,可以认为时间准确到3%以内)

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

    SQL Server 解析和编译时间:
    CPU 时间 = 3 毫秒,经过的时间 = 3 毫秒。
    表“元数据服务”。扫描计数 1,逻辑读取 55402,物理读取 0,预读读取 159,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

    SQL Server 执行时间:
    CPU 时间 = 20469 毫秒,经过时间 = 21238 毫秒。

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

    SQL Server 解析和编译时间:
    CPU 时间 = 0 毫秒,经过的时间 = 1 毫秒。
    表“元数据服务”。扫描计数 1,逻辑读取 55402,物理读取 0,预读读取 3,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

    SQL Server 执行时间:
    CPU 时间 = 11219 毫秒,经过时间 = 12030 毫秒。
    CPU 时间 = 11531 毫秒,经过时间 = 12148 毫秒。

    固定数字 vs PATINDEX vs CHARINDEX

    (上面已经给出了固定位置版本)
    性能总结 - FIXED > (PATINDEX = CHARINDEX)
    那里PATINDEX 和 CHARINDEX 之间似乎没有实质性区别

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

    SQL Server 解析和编译时间:
    CPU 时间 = 0 毫秒,经过的时间 = 2 毫秒。
    表“元数据服务”。扫描计数 1,逻辑读取 55400,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

    SQL Server 执行时间:
    CPU 时间 = 15218 毫秒,经过时间 = 16167 毫秒。

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

    SQL Server 解析和编译时间:
    CPU 时间 = 0 毫秒,经过的时间 = 3 毫秒。
    表“元数据服务”。扫描计数 1,逻辑读取 55402,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

    SQL Server 执行时间:
    CPU 时间 = 15469 毫秒,经过时间 = 16353 毫秒。

    注意事项:

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

    注意!

    即使 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.')
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2021-04-17
        • 2016-04-03
        • 1970-01-01
        • 1970-01-01
        • 2020-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多