0

我有以下声明:

UPDATE Table SET Column=Value WHERE TableID IN ({0})

我有一个逗号分隔的 TableID 列表,它可能很长(用于替换 {0})。我发现这比使用 SqlDataAdapter 更快,但是我也注意到如果命令文本太长,SqlCommand 可能会表现不佳。

有任何想法吗?

这是在 CLR 触发器内部。每个 SqlCommand 执行都会产生某种开销。我已经确定上述命令比 SqlDataAdapter.Update() 更好,因为 Update() 将更新单个记录,从而导致执行多个 SQL 语句。

...我最终做了以下事情(触发时间从 0.7 秒到 0.25 秒)

UPDATE T SET Column=Value FROM Table T INNER JOIN INSERTED AS I ON (I.TableID=T.TableID)
4

4 回答 4

0

如果这是一个存储过程,我将使用表值参数。如果这是一个临时批处理,那么请考虑填充一个临时表并在您的批处理中加入它。您的 IN 子句被合理化为一堆 OR,它们可以很容易地否定索引的使用。使用 JOIN,您可能会从优化器中获得更好的计划。

DECLARE @Value VARCHAR(100) = 'Some value';
CREATE TABLE #Table (TableID INT PRIMARY KEY);
INSERT INTO #Table VALUES (1),(2),(3),(n)...;
MERGE INTO Schema.Table AS target
USING #Table AS source
ON target.TableID = source.TableID
WHEN MATCHED THEN UPDATE SET Column = Value;
于 2013-03-18T20:01:36.967 回答
0

当列表很长时,执行计划可能是使用索引扫描而不是索引查找。在这种情况下,您最好将列表限制为几个项目,但重复调用更新命令,直到列表中的所有项目都被容纳。

于 2013-03-18T19:46:03.313 回答
0

将您的 ID 列表拆分为批次。我假设您有集合中的 id 编号列表,并且您正在构建{0}字符串。所以可能一次更新 20 或 100 个。

将其包装在事务中并在调用 Commit() 之前执行所有更新

于 2013-03-18T19:46:49.467 回答
0

如果可以使用存储过程,则可以改用MERGE语句。

MERGE INTO Table AS target
USING @TableIDList AS source
ON target.TableID = source.ID
WHEN MATCHED THEN UPDATE SET Column = source.Value

哪里@TableIDList是从代码作为表值参数发送的表类型ID,其中包含您需要的s(可能还有Values)。

于 2013-03-18T19:51:53.277 回答