我有以下声明:
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)
答案 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;