使用每行計數 (*) 更新本地表,它是遠端伺服器上內部連接的聚合
我在連結伺服器上有一個大約 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
根據您的權限,連結伺服器可能會嘗試在本地流式傳輸所有數據,然後進行過濾。參考
- 在視圖中使用 OPENQUERY 的性能影響
- 哪個更有效:從連結伺服器中選擇或插入連結伺服器?
- http://blogs.msdn.com/b/psssql/archive/2009/09/02/distributed-queries-remote-login-permissions-and-execution-plans.aspx
您可以通過首先將總聚合計數計算到本地伺服器上的表中,然後與之抗衡,從而避免這種痛苦。
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;