在复制大量数据并将其插入同一个表的插入语句中使用ROWLOCK是否明智?
例)
INSERT INTO TABLE with (rowlock) (id, name)
SELECT newid, name
FROM TABLE with (nolock)
WHERE id = 1
是否有人建议如何改进此声明,因为我看到当SQL Server变得忙碌时,它将以SQL Server返回的超时查询结束。
答案 0 :(得分:1)
您可能最好先将子查询结果存储在临时表中并插入。
答案 1 :(得分:0)
如果您要插入大量数据并且您有读者/编写者问题(锁定,超时),您可能应该将插入内容分成多个部分(前100个或其他内容),直到您完成所有数据。如果不这样做,即使您声明了rowlock,也可能会发生锁升级,在这种情况下,SQL Server将在您插入数据时获取表锁。
另一个不错的选择是使用SNAPSHOT隔离,如果你有足够的空间,这将是完美的。 对于第一个选项,请阅读Q
答案 2 :(得分:0)
如果要插入大量数据,例如1000行或更多,则可以考虑使用临时表或表变量。首先将行插入临时表或变量,然后执行insert到final_table select * from temp table将非常有效。如果你需要更多行,那么只需将插入放在游标中并迭代说每1000行直到总行数完成。
对于更复杂的插入,如果您需要保留身份密钥,或将其用作其他表中的引用密钥,您可以将整个存储过程放入事务中,并计算最终表中最后使用的身份密钥,并将其用作临时表的标识键的第一个值,或设置标识已关闭。
答案 3 :(得分:0)
嗯,不能在INSERT语句中使用WITH(NOLOCK)表提示。见https://docs.microsoft.com/en-us/sql/t-sql/statements/insert-transact-sql#arguments
如果在任何给定时间只有一个进程或应用程序在同一个表中复制数据,那么各种事务隔离级别对您没有太大作用。它们旨在隔离(分离)不同的交易,并且对单个交易没有影响。
此外,通常最好将查询优化委托给SQL Server,因为查询的所有必要元素都是已知的,并且 - 我假设 - 没有针对同一个表的其他竞争查询,这可能搞砸了优化的查询执行计划。