在SQL存储过程中运行缓慢的多个Update语句

时间:2014-08-20 15:23:56

标签: performance sql-server-2008 tsql stored-procedures sql-update

请参阅下面的SQL命令,它是存储过程的一部分。存储过程创建一个名为#TREPORT的临时表,然后在SODATE列上执行以下多个更新。

临时表(#TREPORT)有大约100万条记录,而以下语句使性能变慢。我该如何进一步改进?

@SDATE和@EDATE是参数,它们是开始日期和结束日期。

提前致谢。

   UPDATE #TREPORT SET 
          SODATE  = '1900-01-01 00:00:00.000' where #TREPORT.SODATE is NULL

   UPDATE #TREPORT SET 
          SODATE  = (SELECT TOP 1 docdate from SO200 
          where SO200.NUMBORIG = #TREPORT.SOPNr 
          AND SO200.SOTYPE = '3' 
    --         AND 
    --DOCDATE is not null and DOCDATE >= '' +CONVERT(varchar(10),@SDATE,101) +''
    --         and DOCDATE <= '' +CONVERT(varchar(10),@EDATE,101) +''
      ) 
          where #TREPORT.SODATE = '1900-01-01 00:00:00.000' or #TREPORT.SODATE is NULL

   UPDATE #TREPORT SET 
          SODATE  = (SELECT TOP 1 docdate from SO100 
          where SO100.NUMBORIG = #TREPORT.SOPNr 
          AND SO100.SOTYPE = '3' 
    --         AND 
    --DOCDATE is not null and DOCDATE >= '' +CONVERT(varchar(10),@SDATE,101) +''
    --         and DOCDATE is not null and DOCDATE <= '' +CONVERT(varchar(10),@EDATE,101) +''
      ) 
      where #TREPORT.SODATE = '1900-01-01 00:00:00.000'  or #TREPORT.SODATE is NULL

   UPDATE #TREPORT SET 
          RowValue = 'C' where 
      (#TREPORT.SODATE < '' +CONVERT(varchar(10),@SDATE,101) +''
          or #TREPORT.SODATE > '' +CONVERT(varchar(10),@EDATE,101) +'')

   UPDATE #TREPORT SET 
          RowValue = 'D' where #TREPORT.SODATE  = '1900-01-01 00:00:00.000' 
          or #TREPORT.SODATE is NULL

1 个答案:

答案 0 :(得分:1)

大批量更新最好分批进行。请参阅此处的解决方案:

http://www.sqlusa.com/bestpractices/largeupdate/

至于组合您的更新,您的第一次更新完全是多余的,因为您要用默认值替换NULL,而其他更新替换&#34; NULL或{默认值}&#34;,所以你可以完全跳过第一个。

其他4个更新可以与CASE语句合并为一个。

UPDATE #TREPORT SET SODATE=CASE
  WHEN EXISTS(SELECT * from SO200 where SO200.NUMBORIG = #TREPORT.SOPNr AND SO200.SOTYPE = '3')
    THEN (SELECT TOP 1 docdate from SO200 
          where SO200.NUMBORIG = #TREPORT.SOPNr 
          AND SO200.SOTYPE = '3')
  WHEN EXISTS(SELECT * from SO100 where SO100.NUMBORIG = #TREPORT.SOPNr AND SO100.SOTYPE = '3')
    THEN (SELECT TOP 1 docdate from SO100 
          where SO100.NUMBORIG = #TREPORT.SOPNr 
          AND SO100.SOTYPE = '3')
  ELSE '1900-01-01 00:00:00.000' 
END
,  RowValue=CASE
  WHEN       (#TREPORT.SODATE < '' +CONVERT(varchar(10),@SDATE,101) +''
          or #TREPORT.SODATE > '' +CONVERT(varchar(10),@EDATE,101) +'')
    THEN 'C'
  ELSE 'D'
END
where #TREPORT.SODATE = '1900-01-01 00:00:00.000' or #TREPORT.SODATE is NULL