【问题标题】:Two queries. Same Output. One takes 2 hours and the other 0 seconds. Why?两个查询。相同的输出。一个需要 2 小时,另一个需要 0 秒。为什么?
【发布时间】:2012-08-08 07:09:28
【问题描述】:

我将一些 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

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

查询 1:

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 上具有相关索引,但令人困惑的是,手动构建的查询立即运行,表明出现了问题在查询优化阶段。

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

【问题讨论】:

    标签: sql sql-server-2008 query-optimization linked-server


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

    • +1 老实说,我不知道!谢谢你的澄清。那么如何将我的本地值发送到远程链接服务器并取回结果呢? CURSORs 然后一次发送一个标识符?远程表很大,大约有 1000 万行。
    • 可能你最好的选择是动态地构造 sql 以针对远程服务器执行并执行它。我们发现,对于我们对链接服务器进行的每种类型的调用,这种方法要快得多。使用游标然后一次运行一个查询可能会导致您达到交易速度限制;你可能不想要。
    • 感谢您的建议。没有更多的瓶颈,我的脚本在这个优化下运行良好。
    【解决方案2】:

    作为参考,这是我根据@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
    

    【讨论】:

    • 这正是我的处理方式。
    • @ChrisLively:感谢您的确认 :)
    猜你喜欢
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 2011-04-23
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多