优化SQL UPDATE语句/ SqlCommand

时间:2013-03-18 19:42:52

标签: sql-server tsql triggers clr sqlcommand

我有以下声明:

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

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

有什么想法吗?

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

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

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

4 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

将其包装在事务中并在调用Commit()

之前执行所有更新

答案 2 :(得分: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 table type从代码发送为表值参数,并带有ID s(可能还有Value s)。

答案 3 :(得分: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;