Answers:
这实际上取决于要更改的数据量。可以说该表有20列。而且,您还有5个索引-每个都在差异上。柱。
现在,如果所有20列中的值都在更改,或者即使5列中的数据正在更改并且这5列都已建立索引,那么“删除和插入”可能更好。但是,如果仅2列发生变化,并且可以说这些列不是任何非聚集索引的一部分,那么最好“更新”记录,因为在这种情况下,仅聚集索引将被更新(索引不必进行更新)。
在进一步的研究中,我确实发现我的上述评论有点多余,因为SQL Server在内部具有2个独立的机制来执行UPDATE。-“就地更新”(即,通过将列值更改为原始行中的新值)或作为“非就地更新”(DELETE后跟INSERT)。
规则是就地更新,并在可能的情况下执行。在这里,行以相同的范围完全位于同一页上的相同位置。仅更改受影响的字节。日志只有一条记录(前提是没有更新触发器)。如果要更新堆(并且页面上有足够的空间),则会进行更新。如果集群键发生更改,但行完全不需要移动,更新也会在原地进行。
例如:如果您的姓氏上有一个聚集索引,并且您有以下名称:Able,Baker,Charlie现在,您想将Baker更新为Becker。无需移动任何行。因此,这可以就位。而如果您必须将Able更新为Kumar,则必须对行进行移位(即使它们在同一页上)。在这种情况下,SQL Server将先执行DELETE,再执行INSERT。
考虑到上述情况,我建议您执行常规的UPDATE,并让SQL Server找出在内部进行更新的最佳方法。
有关“ UPDATE”内部或有关SQL Server相关内部的更多详细信息,请参阅Kalen Delaney,Paul Randal等人的书 -SQL Server 2008 Internals。
您是否研究了SQL 2008中的MERGE命令?这是一个基本示例:
merge YourBigTable ybt
using (select distinct (RecordID) from YourOtherTable) yot
on yot.Recordid = YBT.RecordID
when NOT matched by target
then insert (RecordID)
values (yot.DeviceID) ;
这基本上是一个“ UPSERT”命令。如果存在则更新,如果不存在则插入。非常快,非常酷的命令。
更新不是那么快。实现快速插入的技巧是在插入数据时禁用索引。
考虑使用此:
-- disable indexes
ALTER INDEX [index_name] ON dbo.import_table DISABLE
-- ... disable more indexes
-- don't use delete if you don't care about minimal logging. truncate is faster
TRUNCATE TABLE dbo.import_table
-- just insert the new rows
INSERT dbo.import_table
SELECT
*
FROM
dbo.source_table
-- rebuild indexes
ALTER INDEX [index_name] ON dbo.import_table REBUILD
-- ... rebuild more indexes
更快的方法是也关闭db选项中的自动统计信息更新。如果表发生了重大变化,则应运行:
UPDATE STATISTICS dbo.import_table
要么
EXEC sp_updatestats
定期(每天,每周一次,具体取决于数据库大小)作为工作,以使统计信息保持最新。需要注意的是在表为空时更新统计信息。如果您在重新填充表格后不运行统计信息,则会破坏统计信息。