Sql-Server

使用每行計數 (*) 更新本地表,它是遠端伺服器上內部連接的聚合

  • September 20, 2013

我在連結伺服器上有一個大約 350m 行的表,我在其中添加了一個額外的 INT 列作為 PACKAGE 和 DOC2 連接的結果作為記錄的計數(external_identification)。由於表太大,我想分批處理更新,這樣我就可以衡量進度並避免創建巨大的臨時表。每列都有索引。

這會是 CTE 發揮作用的一個很好的例子嗎?老實說,他們讓我對他們需要編寫的方式感到困惑,很難想像……

這些表的結構如下:

ServerA(實用程序 SQL 伺服器)

表:CLIP_IDs

列:Package_UUID nvarchar(255)、MessageExtractState tinyint、

$$ count $$整數(350m 行) ServerB(主數據庫伺服器)

表:PACKAGE

列:Package_UUID nvarchar(255),Package_id bigint(650m 行)

表:DOC2

列:External_Identification nvarchar(255),Package_id bigint(2b 行)

如果從一個 SQL 伺服器啟動查詢效率更高,則兩個 SQL 伺服器都以兩種方式連結。我感覺會從 ServerA 發出查詢,因為執行計劃似乎提供的遠端查詢較少。

我在 26 小時後停止了下面的查詢,因為我認為我有語法邏輯錯誤。有人可以解釋它是什麼並提供任何建議嗎?

從伺服器 A 執行:

DECLARE @rowsUpdated INT

SET @rowsUpdated = 1

WHILE (@rowsUpdated > 0)
BEGIN
   UPDATE CLIP_IDs
   SET [Count] = x.[count]
   FROM (
       SELECT TOP 50000 c.package_uuid
           ,count(d.external_identification) AS [count]
       FROM CLIP_IDs c
       INNER JOIN ServerB.DATABASE.dbo.package p(NOLOCK) ON c.package_uuid = p.package_uuid
       INNER JOIN ServerB.DATABASE.dbo.doc2 d(NOLOCK) ON p.package_id = d.package_id
       WHERE c.messageextractstate = 1
           AND c.[count] IS NULL
       GROUP BY c.package_uuid
       ) x

   SET @rowsUpdated = @@rowcount

   PRINT N'Finished set of rows: ' + convert(VARCHAR, getdate(), 120)
END

根據您的權限,連結伺服器可能會嘗試在本地流式傳輸所有數據,然後進行過濾。參考

您可以通過首先將總聚合計數計算到本地伺服器上的表中,然後與之抗衡,從而避免這種痛苦。

CREATE TABLE #LOCAL
(
   package_uuid nvarchar(255) NOT NULL PRIMARY KEY CLUSTERED
,   [count] bigint
);

INSERT INTO
   #LOCAL
SELECT 
   p.package_uuid
,   count(d.external_identification) AS [count]
FROM 
   ServerB.DATABASE.dbo.package p
   INNER JOIN 
       ServerB.DATABASE.dbo.doc2 d
       ON p.package_id = d.package_id
GROUP BY 
   p.package_uuid;

首先嘗試在 ServerB 上本地執行該查詢,以了解理論吞吐量,而不考慮您的網路。然後,您可以根據數據大小(臨時表中每行 500 + 8 個)進行一些快速而骯髒的估計,然後這取決於您的網路。希望這都是本地網路。

如果在 ServerB 上執行和將其拉回之間的時間明顯不同,那麼您可能需要使用 OPENQUERY 語法來強制遠端伺服器上的連接。程式碼大約

CREATE TABLE #LOCAL
(
   package_uuid nvarchar(255) NOT NULL PRIMARY KEY CLUSTERED
,   [count] bigint
);

INSERT INTO
   #LOCAL
SELECT
   OQ.package_uuid
,   OQ.[count]
FROM
   OPENQUERY(ServerB,
   N'
   SELECT 
       p.package_uuid
   ,   count(d.external_identification) AS [count]
   FROM 
       DATABASE.dbo.package p
       INNER JOIN 
           DATABASE.dbo.doc2 d
           ON p.package_id = d.package_id
   GROUP BY 
       p.package_uuid
   ) AS OQ;

引用自:https://dba.stackexchange.com/questions/50228