[英]How can I improve the performance of this stored procedure?
好的,所以我對我們擁有的存儲過程進行了一些更改,現在需要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
獲取數據並更新#tCustomersEmail
表中的OrderDate
,只要CustomerNumber
匹配, OrderDate
為null:
UPDATE #tCustomersEmail
SET OrderDate = InvcDate
FROM #tCustomersEmail
INNER JOIN #tSouth ON #tCustomersEmail.CustomerNumber = [#tSouth].CustID
where #tCustomersEmail.OrderDate IS null
進行這些更改會導致存儲過程采用FOR-EV-ER(Sandlot參考!)
那么我做錯了什么?
順便說一下,我創建它們之后在我的臨時表上創建索引:
create clustered index idx_Customers ON #tCustomersEmail(CustomerNumber)
CREATE clustered index idx_CustSouthW ON #tSouth(CustID)
嘗試跳過#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
我不認為索引會在這個例子中幫助你
也許使用表變量而不是臨時表?
declare @temp table
(
CustID char(10),
InvcDate nchar(10)
)
insert into @temp
...
這肯定會提高性能!
如果您有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
很難預測涉及鏈接服務器上的表的復雜查詢的行為,因為本地服務器無法訪問遠程表的統計信息,並且因此可能最終得到一個糟糕的查詢計划 - 它將在假設遠程表有1或100行。 如果這還不夠糟糕,錯誤計划的結果可能是將整個遠程表通過線路拉到本地臨時空間並在那里進行處理。 如果遠程表非常大,這可能是主要的性能開銷。
可能值得嘗試簡化鏈接服務器查詢以最小化整個表通過線路返回的可能性 - (如已經提到的,您不需要DISTINCT
和GROUP BY
)
INSERT INTO #tSouth(CustID, InvcDate)
SELECT [CustID],
max(InvcDate) as InvcDate
FROM D3.SouthW.dbo.uc_InvoiceLine I
group BY I.CustID
保持查詢的其余部分不變。
但是,由於聚合,這可能仍然將整個表格帶回本地服務器 - 您需要進行測試才能找到答案。 您最好的選擇可能是將此邏輯封裝在SouthW數據庫的視圖中,如果您能夠在其中創建對象,則從SP代碼中引用該邏輯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.