5

我在临时表中插入了一些 ID #A,如下所示:

SELECT DISTINCT ID
INTO #A
FROM LocalDB.dbo.LocalTable1
WHERE ID NOT IN (SELECT DISTINCT ID FROM LocalDB.dbo.LocalTable2)
GO

CREATE INDEX TT ON #A(ID)
GO

我正在尝试使用我在前一阶段收集的标识符从远程链接服务器获取一些信息:

查询一:

SELECT ID, Desc
FROM RemoteLinkedServer.DB.dbo.RemoteTable X
WHERE ID IN (SELECT ID FROM #A)

查询 2:

SELECT ID, Desc
FROM RemoteLinkedServer.DB.dbo.RemoteTable X
INNER JOIN #A Y
ON X.ID = Y.ID

现在在下面的查询中,我正在做的是获取临时表的输出,复制行并将它们正确格式化为逗号分隔的列表,然后手动将其放入查询中。

查询 3:

SELECT ID, Desc
FROM RemoteLinkedServer.DB.dbo.RemoteTable X
WHERE ID IN (-- Put all identifiers here --)

查询12执行需要 2 小时,查询3需要 0 秒(我的临时表包含大约 200 行)。我不知道发生了什么,也没有权限检查远程服务器是否在 ID 上有相关索引,但令人困惑的是,手动构建的查询立即运行,表明出现了问题在查询优化阶段。

关于这里出了什么问题或如何加快查询速度的任何想法?

4

2 回答 2

10

查询 1 和 2 会导致 RemoteTable 中的所有数据都被拉入本地数据库,以便执行连接操作。这会消耗 RAM、网络带宽,并且在执行查询时通常会非常慢。

查询 3 允许远程服务器过滤结果以仅发送您想要的匹配项。

基本上,它归结为谁来做这项工作。查询 1/2 需要您的本地数据库来执行;查询 3 让远程执行此操作。

如果您在该远程表中有大量数据,那么您可能会遇到网络拥塞等问题。

查询链接服务器的最佳方法是构建查询,例如远程服务器完成所有工作并将结果发送回本地服务器。这将优化获取所需数据所需的网络、内存和磁盘资源量。

任何时候您必须跨服务器边界加入(使用链接服务器),这将是一场灾难。

于 2012-08-11T00:40:44.447 回答
3

作为参考,这是我根据@ChrisLively 的建议解决问题的方法:

SELECT DISTINCT ID
INTO #A
FROM LocalDB.dbo.LocalTable1
WHERE ID NOT IN (SELECT DISTINCT ID FROM LocalDB.dbo.LocalTable2)
GO

CREATE INDEX TT ON #A(ID)
GO

DECLARE @IDList VARCHAR(MAX)
SELECT @IDList=(SELECT TOP 1 REPLACE(RTRIM((
                SELECT DISTINCT CAST(ID AS VARCHAR(MAX)) + ' ' 
                FROM #A AS InnerTable               
                FOR XML PATH (''))),' ',', '))
FROM #A AS OuterResults


DECLARE @sql AS varchar(MAX)
SET @sql = 'SELECT * FROM RemoteLinkedServer.RemoteDB.dbo.RemoteTable X WHERE ID IN (' + @IDList + ')'

EXEC (@sql)

DROP TABLE #A
GO
于 2012-08-11T01:07:11.117 回答