Sql-Server

為什麼 SQL Server 在更新位列時掃描所有行,即使是通過連結伺服器的主鍵

  • September 14, 2022

我正在為 SQL 連結伺服器的特定主鍵使用簡單的更新語句,如下所示

UPDATE t
SET
   processed = 1,
   processed_on = GETDATE()
FROM [LINKED\SERVER].DATABASE.dbo.FileQueue t
WHERE t.FileId = '3b33eff6-fde1-4e8c-9c23-2dbd45f50222'

兩台伺服器都是 SQL Server 2019。表定義是

CREATE TABLE dbo.FileQueue
(
   FileId UNIQUEIDENTIFIER NOT NULL,
   Processed BIT NOT NULL,
   Processed_on DATETIME NULL
CONSTRAINT PK_FileQueue PRIMARY KEY CLUSTERED 
(
   FileId ASC
)
)

Processed 列具有位類型。由於全表掃描,查詢速度很慢。

查詢計劃

為什麼會這樣?當我從語句中刪除位列時,一切正常,讀取和更新單個遠端行。

Id列是聚集的主鍵。我有很多具有相似鍵的表。

我嘗試了CONVERTorCAST函式,結果是一樣的。

對於沒有位列的查詢,執行計劃非常好。

UPDATE t
SET
   --processed = 1,
   -- any other columns can be added to be updated except bit
   processed_on = GETDATE()
FROM [LINKED\SERVER].DATABASE.dbo.FileQueue t
WHERE t.FileId = 'ABD4442F-8560-43B5-8B04-000000B2A626'

查詢計劃

理想情況下,您將呼叫遠端伺服器上的儲存過程來進行此修改,並將 UUID 作為參數。

同時,嘗試為bit常量使用一個變數:

DECLARE @true bit = 1;

UPDATE t
SET processed = @true,
   processed_on = GETDATE()
FROM [LINKED\SERVER].DATABASE.dbo.Queue t
WHERE
   t.Id = CONVERT(uniqueidentifier, '3b33eff6-fde1-4e8c-9c23-2dbd45f50222');

或者,如果您的連結伺服器配置為RPC OUT,請使用EXECUTE...AT

DECLARE 
   @id uniqueidentifier = {GUID '3b33eff6-fde1-4e8c-9c23-2dbd45f50222'},
   @processed bit = 1,
   @processed_on datetime = GETDATE();

EXECUTE 
(
   -- Parameterized statement
   N'
   UPDATE [DATABASE].dbo.Queue 
   SET processed = ?, 
       processed_on = ? 
   WHERE Id = ?',
   --- Parameter values
   @processed,
   @processed_on,
   @id
)
AT [LINKED\SERVER];

在遠端伺服器上擷取的計劃:

遠端計劃

如果您在沒有 RPC 的單個本地語句中需要它:

UPDATE t
SET processed = V.processed,
   processed_on = GETDATE()
FROM [LINKED\SERVER].DATABASE.dbo.Queue AS t
CROSS JOIN (VALUES(1)) AS V (processed)
WHERE
   T.Id = CONVERT(uniqueidentifier, '3b33eff6-fde1-4e8c-9c23-2dbd45f50222');

計劃

SQL Server 使用稱為分佈式查詢(DQ) 的框架將您的 SQL 轉換為遠端伺服器可以理解的形式。DQ 中的某些東西比其他東西更有效。bit數據類型總是有點奇怪。

這當然是一個錯誤。如果您想報告它,您可以通過 Microsoft 支持以通常的方式進行報告,或者在https://aka.ms/sqlfeedback

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