如何提高此存储过程的性能?

时间:2011-12-14 22:03:40

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

好的,所以我对我们拥有的存储过程进行了一些更改,现在需要3个小时才能运行(之前只需要10分钟)。我有一个名为#tCustomersEmail的临时表。在其中,是一个名为OrderDate的列,其中包含许多空值。我想用另一台服务器上的另一个数据库中的数据替换这些空值。所以这就是我所拥有的:

我创建另一个临时表:

Create Table #tSouth
(
CustID char(10),
InvcDate nchar(10)
)

我填充了这些数据:

INSERT INTO #tSouth(CustID, InvcDate)
SELECT DISTINCT
      [CustID],
      max(InvcDate) as InvcDate
  FROM D3.SouthW.dbo.uc_InvoiceLine I
  where EXISTS (SELECT CustomerNumber FROM #tCustomersEmail H WHERE   I.CustID =  H.CustomerNumber) 
  group BY I.CustID

然后我从#tSouth获取数据并更新OrderDate表格中的#tCustomersEmail,只要CustomerNumber匹配,OrderDate为空:

UPDATE #tCustomersEmail  
SET OrderDate = InvcDate 
FROM #tCustomersEmail  
INNER JOIN #tSouth ON #tCustomersEmail.CustomerNumber = [#tSouth].CustID
where #tCustomersEmail.OrderDate IS null

进行这些更改会导致存储过程采用FOR-EV-ER(Sandlot reference!)

那么我做错了什么?

BTW我在创建它们之后在我的临时表上创建索引:

create clustered index idx_Customers ON #tCustomersEmail(CustomerNumber)
CREATE clustered index idx_CustSouthW ON #tSouth(CustID)

4 个答案:

答案 0 :(得分:3)

尝试跳过#tsouth表并使用此查询:

UPDATE a
SET OrderDate = (select max(InvcDate) from D3.SouthW.dbo.uc_InvoiceLine I 
                 where a.customernumber = custid)  
FROM #tCustomersEmail a  
WHERE orderdate is null

我不认为索引会在这个例子中帮助你

答案 1 :(得分:3)

也许使用表变量而不是临时表?

declare @temp table
(
    CustID char(10),
    InvcDate nchar(10)
)

insert into @temp
...

这肯定会提高性能!

答案 2 :(得分:2)

如果您有GROUP BY,则不需要区别。鉴于你跨越数据库,我不喜欢EXISTS。我会更改该部分以限制该点的行数。改为:

INSERT INTO #tSouth(CustID, InvcDate)
SELECT 
      [CustID],
      max(InvcDate) as InvcDate
  FROM D3.SouthW.dbo.uc_InvoiceLine I
  where I.CustID in 
       (SELECT CustomerNumber 
        FROM #tCustomersEmail H 
        WHERE H.OrderDate IS null ) 
  group BY I.CustID

编辑:仔细观察你确定应该使用uc_InvoiceLine吗?看起来应该有一个父表,该表具有日期并且行数较少。 此外,您可以直接执行更新来跳过一个临时表:

UPDATE #tCustomersEmail  
SET OrderDate = InvcDate 
FROM #tCustomersEmail  
INNER JOIN (SELECT 
      [CustID],
      max(InvcDate) as InvcDate
  FROM D3.SouthW.dbo.uc_InvoiceLine I
  where I.CustID in 
       (SELECT CustomerNumber 
        FROM #tCustomersEmail H 
        WHERE H.OrderDate IS null ) 
  group BY I.CustID) Invoices
ON #tCustomersEmail.CustomerNumber = Invoices.CustID

答案 3 :(得分:2)

很难预测涉及链接服务器上的表的复杂查询的行为,因为本地服务器无法访问远程表的统计信息,并且因此可能会导致查询计划不佳 - 它将起作用假设远程表有1行或100行。 如果这还不够糟糕,错误计划的结果可能是将整个远程表通过线路拉到本地临时空间并在那里进行处理。如果远程表非常大,这可能是一个主要的性能开销。

可能值得尝试简化链接服务器查询以最小化整个表通过线路返回的可能性 - (如前所述,您不需要DISTINCT和{{1 }})

GROUP BY

保持查询的其余部分不变。

但是,由于聚合,这可能仍会将整个表格带回本地服务器 - 您需要进行测试才能找到答案。您最好的选择是将此逻辑封装在SouthW数据库的视图中,如果您能够在其中创建对象,则从您的SP代码中引用该逻辑。