2014-11-25 40 views
1

我有2個數據庫坐在不同的物理服務器上並鏈接在一起。我需要使用DB2.T2加入DB1.T1並創建一個id。問題在於性能。我的資深人員堅持使用一個函數,並在下面創建它。tsql - 將不同數據庫中的兩個表連接到不同的服務器上

IF OBJECT_ID (N'dbo.getXXXId', N'FN') IS NOT NULL 
    DROP FUNCTION dbo.getTRId; 
GO 
CREATE FUNCTION dbo.getTRId (@gcPRef bigint) 
RETURNS varchar (100) 
WITH EXECUTE AS CALLER --may not be necessary. not sure. 
AS 
BEGIN 

    DECLARE @TRID varchar (100); 
    SELECT @TRID = CONVERT(varchar (12), hu2.PropId) 
       + '_'+ CONVERT(varchar (12), c.WSId) 
     FROM [172.29.110.133].DB1.dbo.checks c 
     join [172.29.110.133].DB1.[dbo].VHier 
          ON VHier.xx= c.xx 
     join [172.29.110.133].DB1.[dbo].rvc 
          ON rvc.xx= VHier.xx 
          AND rvc.yy= VHier.yy 
     join [172.29.110.133].DB1.[dbo].HUNIT hu 
          ON c.xx= hu.xx 
    WHERE c.CheckId = @gcPRef; 

    RETURN (@TRID); 
END; 
GO 

我使用下面的查詢來使用上面的函數來查詢每個checkid。

select getTRId(guestCheckPRef), guestCheckid from DB2.Guest_CHECKS GC 
where GC.closeBusinessDate = '2014-06-25' 

你可能喜歡的幾件事情知道:

  • DB1和DB2在不同的物理服務器託管。
  • 我不是DBA,所以請讓我知道如果我做錯了什麼。
  • 每天創建約45000條記錄。所以這是行的數量..
  • 我已經嘗試加入他們沒有涉及的功能。它需要永遠。在30秒內,僅返回450條記錄。我無法長時間鎖定表格。
  • 約束[DB1.PK_CHECK] PRIMARY KEY CLUSTERED
  • 約束[DB2.XPKGUEST_CHECKS] PRIMARY KEY NONCLUSTERED
  • 我不知道,如果限制在這裏發揮作用。 DB2.GUEST_CHECKS.guestCheckPRef在這裏甚至不是FK。 guestCheckPRef是DB1.CHECK中的PK。
  • 表現很差。我需要返回DB2.propid + DB2.wsid + DB1.guestCheckid。

這是我現在可以給予的。任何建議表示讚賞。它不一定要用一個函數來完成。

在此先感謝。 Regards.Oz。

+1

您是否試圖在DB1本身具有此功能?因爲你的函數不使用任何DB2表。只需在本地數據庫中具有該功能並從其他數據庫調用它。 – NMK 2014-11-25 01:55:51

+3

鏈接的服務器幾乎**總是會破壞你的性能。無論您的查詢的其餘部分如何精心調整,鏈接的服務器都會讓您失望。另外,你爲什麼要做這個功能而不是存儲過程? – alroc 2014-11-25 02:12:09

+0

@NMK。謝謝。也許我沒有說清楚。這個函數存儲在DB2上,遠程訪問DB1。是的,我已經將該功能存儲在DB1上,並試圖從DB2遠程訪問該功能,因爲消息來源說您無法遠程調用某個功能。除了我們的客戶端將使用這個,他們只能訪問DB2.Regards.Oz。 – Ozland 2014-11-25 04:59:49

回答

1

這裏有一些事情要嘗試或考慮:

  1. 是否檢查該查詢使用最好的指標?您可以嘗試通過查詢分析器運行查詢,以查看是否有可以添加的任何索引來提高性能。

  2. 您運行的是哪個版本的SQL Server?根據不同的版本,您可以將表從一臺服務器複製到另一臺服務器,以減輕在網絡上運行查詢的成本。

  3. 我注意到幾個連接到另一個服務器 - 你可以將所有這些連接合併到一個使用索引優化的單個視圖中 - 可能會導致較少的網絡流量。

  4. 嘗試將您的功能放在另一臺服務器上,並從第一臺服務器調用它來查看是否有任何性能改進。

+0

我認爲#4這裏將是最好的選擇,而不需要在服務器之間複製數據。 – alroc 2014-11-25 13:43:53

0

在功能中做「選擇」通常被認爲「不是一個好主意」。對於結果集中的每一行,函數中的選擇將重複一次,這可能是性能不佳的原因。

Erp。這應該是一個評論,而不是一個答案。要將此轉換爲適當的答案,請將查詢重寫爲聯接,而不使用該函數。 (即走功能的內容,並將其整合到一個單一的加入。)

你的榜樣查詢應該是這個樣子:

;with getTRID as 
(SELECT CONVERT(varchar (12), hu2.PropId) 
    + '_'+ CONVERT(varchar (12), c.WSId) AS TRID 
    FROM [172.29.110.133].DB1.dbo.checks c 
join [172.29.110.133].DB1.[dbo].VHier 
    ON VHier.xx= c.xx 
join [172.29.110.133].DB1.[dbo].rvc 
    ON rvc.xx= VHier.xx 
    AND rvc.yy= VHier.yy 
join [172.29.110.133].DB1.[dbo].HUNIT hu 
    ON c.xx= hu.xx) 
select getTRId.TRID, guestCheckid from DB2.Guest_CHECKS GC 
inner join getTRID ON CheckId = guestCheckPRef 
where GC.closeBusinessDate = '2014-06-25' 

注:我在這裏從內存工作,所以,請不要火焰語法錯誤!謝謝。

Steve G.

+0

感謝您的回覆和時間。我已經嘗試過,修復語法並不是什麼大問題。它也是資源密集型的。花費很多時間甚至返回100條記錄。我相信這是一個網絡/鏈接服務器問題。 – Ozland 2014-11-25 04:50:18

+0

如果Time真的是最重要的,另一個建議是在進行任何連接之前,將有問題的數據緩存在所有遠程服務器的「本地」服務器上。我將首先將相關數據選擇到每個服務器上的臨時表中,然後通過網絡複製臨時數據表。這應該會給您對源表的影響最小,並且有助於減少網絡延遲的影響。 – 2014-11-25 17:17:41

相關問題