2015-09-24 103 views
2

我有兩個鏈接的SQL Server(2008R2)。遠程服務器包含具有大量行的表。它必須加入當地的餐桌。在這種情況下,一個好的解決方案是使用REMOTE提示JOIN什麼使用,而不是LEFT REMOTE JOIN

但對於使用REMOTE JOIN限制:

遙控器可以只用於INNER JOIN操作。

我想打一個左聯接操作,但它會在本地端來完成,整個HugeRemoteTable將在本地服務器上加載:

SELECT HugeRemoteTable.* 
FROM HugeRemoteTable 
LEFT JOIN LocalTable 
    ON HugeRemoteTable.col = LocalTable.id 
WHERE LocalTable.id IS NULL 

是否有可能重寫查詢加盟遠程端的表和只加載過濾的數據?

EDIT1:

我嘗試wtih查詢,它看起來像SQL Server查詢遠程如果條件是LocalTable.id IS NULL運行。查詢需要幾次。

但條件爲LocalTable.id IS NOT NULL的查詢需要更多的時間,顯然在本地運行。

相同的行爲顯示查詢JOIN重寫爲NOT ININ(它們甚至具有類似於JOIN查詢計劃的執行計劃)。

此查詢的運行速度很快:

SELECT * 
FROM HugeRemoteTable 
WHERE col NOT IN (SELECT id FROM LocalTable) 

而這其中需要花費大量的時間,併產生大量的請求到遠程服務器的(我不知道到底爲什麼,但它看起來像本地服務器品牌從LocalTable每每一行的請求):

SELECT * 
FROM HugeRemoteTable 
WHERE col IN (SELECT id FROM LocalTable) 

現在我們要OPENQUERY。我已經使用別名「的LocalServer」連接我的本地服務器用作遠程SQL Server鏈接服務器(在相反的方向),並開始與OPENQUERY以這樣的方式

SELECT * FROM OPENQUERY(remote,' 
    SELECT * FROM HugeRemoteTable 
    LEFT JOIN localServer.localTable ON HugeRemoteTable.col=localTable.id 
    WHERE localTable.id is not null') 

它是儘可能快地與條件查詢LocalTable.id IS NULL

SELECT * FROM OPENQUERY(remote,' 
    SELECT * FROM HugeRemoteTable 
    LEFT JOIN localServer.localTable ON HugeRemoteTable.col=localTable.id 
    WHERE localTable.id is null') 

使用OPENQUERY的查詢速度非常快,但它們需要服務器之間的雙向鏈接。

還有其他解決方案嗎?

+0

可能? –

+0

@TabAlleman _not_ in - 也許select * from HugeRemoteTable,其中HugeRemoteTable.col不在(從LocalTable中選擇Id) – Clay

+0

啊,我沒有真正閱讀他的查詢,我只看到了LEFT JOIN,並且認爲「在哪裏」。我沒有看到他想用它來排除本地表中的匹配。接得好。 –

回答

0

OPENQUERY可用於將繁重的執行移動到相應的服務器,並且可以返回結果。

您的左連接本身不會過濾行,因此您必須在遠程查詢中指定where子句或其他連接類型(編輯:除非您在左側指定小表以匹配大表中的行,存在)。

OPENQUERY (Transact-SQL)

1

如果你正在尋找的速度和使用鏈接的服務器,讓這個嘗試。

步驟1)。用你需要的數據創建一個臨時表。 步驟2)。如果你想要速度,使用Openquery是你想要去的方式。用您希望從其他服務器獲得的數據創建一個臨時表。使用openquery和動態sql抓取你想要過濾的數據。步驟3)。使用臨時表來加入這個。

DECLARE @FlatTSQL varchar(8000) 
DECLARE @AsOfDate date = '9/24/2015' 

CREATE TABLE #MyData 
(AsOfDate date) 


SELECT @FlatTSQL = 'SELECT * FROM OPENQUERY(EUC,'' 
               SELECT 
               cal.AsOfDate 
               FROM RiskReporting.Reference.lkpCalendar cal WITH(NOLOCK) 
               WHERE CONVERT(date,cal.AsOfDate) = ''''' + CONVERT(varchar(25),@AsOfDate) + ''''''')' 


INSERT INTO #MyData 
EXEC (@FlatTSQL) 

SELECT 
* 
FROM #MyData md 

DROP TABLE #MyData 

讓我知道,如果它的工作原理,亞歷克斯

用WHERE IN(子查詢)
+0

很難從OPENQUERY訪問我的localTable。我需要將所有ids選擇爲以逗號分隔的字符串,然後在動態查詢中使用它,或者將本地SQL Server作爲鏈接服務器連接到遠程服務器。 –