delete-insert 与 if-update else-insert 的最佳选择是哪个?
Posted
技术标签:
【中文标题】delete-insert 与 if-update else-insert 的最佳选择是哪个?【英文标题】:Which is the best choice in delete-insert vs if-update else-insert? 【发布时间】:2010-12-02 19:29:43 【问题描述】:更新:
我的错...我在这些表上有一个主键..我的意思是目前没有进一步的索引 表。我们可能会在 看到性能之后的未来,因为我们对数据的过滤器太多了 检索数据 上次我们运行数据库时,索引并没有显示出太大的改进 调音。
我有一个包含数百万条记录的 4 个大表。现在有一个存储过程被频繁调用并更新这些表。这是场景 -
现在,如果今天存在条目,我需要为今天更新它,否则如果用户的条目不存在,我需要继续为用户插入一个条目。现在有两种方法可以执行这些操作,因为只有一个 proc 可以执行此操作 -
第一种方式 -
IF EXISTS(TABLE1)
--UPDATE where condn
ELSE
--INSERT
IF EXISTS(TABLE2)
--UPDATE where condn
ELSE
--INSERT
IF EXISTS(TABLE3)
--UPDATE where condn
ELSE
--INSERT
IF EXISTS(TABLE4)
--UPDATE where condn
ELSE
--INSERT
第二种方式-
DELETE from TABLE1 where condn
DELETE from TABLE2 where condn
DELETE from TABLE3 where condn
DELETE from TABLE4 where condn
INSERT TABLE1 ENTRY
INSERT TABLE2 ENTRY
INSERT TABLE3 ENTRY
INSERT TABLE4 ENTRY
现在第二种方式看起来更简单,但可能更耗时......我不确定哪种方式在这里最好。任何人都可以在这里帮助或指导我..谢谢!
【问题讨论】:
由于 MERGE 在 SQL2005 中不可用(感谢那些对此发表评论的人),我更喜欢第一种方式。第二种方式的最坏情况可能是您拥有作为聚集索引的身份,导致每次更改至少有两次写入操作。 OP 说:There is no indexing currently on he tables. We might have it in the future.
和 4 huge tables over millions of records
。请注意,主键为您提供索引。如果你没有PK,那么我说,未来就是现在!以性能的名义,请添加一个索引,这将有助于你的where condn
!
如果删除再插入,SQL Server每次都需要修改主键索引。如果只更新,则可以单独保留索引。这是四个写入操作(删除行、删除索引条目、创建行、创建索引条目)与一个(更新行)。
【参考方案1】:
如果您希望主要是插入,试试这个
...
BEGIN TRY
INSERT table1
END TRY
BEGIN CATCH
IF ERROR_NUMBER = 2627
UPDATE table1
ELSE
--process real error
END CATCH
...
主要是更新...
...
BEGIN TRY
UPDATE table1 ... WHERE ...
IF @@ROWCOUNT = 0
INSERT Table1
END TRY
BEGIN CATCH
--optional. if someone manages to insert before here, do we update it? or just ignore it?
IF ERROR_NUMBER = 2627
UPDATE table1
ELSE
--process real error
END CATCH
...
EXISTS 在高负载下不够并发。如果您要使用 EXISTS 扫描表,您也可以尝试 INSERT。
其他答案:One、Two、Three
编辑:我称之为 JFDI 模式...
【讨论】:
第一次插入时出现此错误:( "当前事务无法提交,不支持写入日志文件的操作。回滚事务。语句已终止。" @andrecarlucci 您可能有 SET XACT_ABORT ON 或“注定”交易的触发器。您应该在更高版本的 SQL 中使用 MERGE @gbn 非常感谢!【参考方案2】:if-exists-then-update-else-insert 方法可能比 delete-insert 的代码更多,但是(取决于索引的数量和类型在表格上定义)它对服务器的工作要少得多。
DELETE 或 INSERT 操作需要修改每个索引,句号。 UPDATE 操作只需要修改这些索引,其字段在此实例中已更新。因此,除非您使用更新修改记录的每个索引字段,否则方法越长效率越高。
编辑:您的问题更新表明,目前除了主键(我假设它是一个聚集键)之外,您没有任何索引。所以比较起来:
当该行已经存在时,它是 1 次聚集索引搜索(假设您通过它们的 PK 找到记录)并且:
delete-insert:4个写操作(删除行、删除PK索引行、插入行、插入PK索引行) check-update/insert:1 次写操作(更新行)当该行尚不存在时,它是 1 次聚集索引查找并且:
delete-insert:2 次写操作(插入行,插入 PK 索引行) check-update/insert:2 次写操作(插入行,插入 PK 索引行)存在的索引越多,删除/插入对已经存在的行执行的效果就越差。此外,由于可避免的写入操作,它可能导致非聚集索引变得不必要地碎片化。
【讨论】:
【参考方案3】:试试这个:
UPDATE TABLE1 where condn
IF @@ROWCOUNT=0
INSERT TABLE1....
UPDATE TABLE2 where condn
IF @@ROWCOUNT=0
INSERT TABLE2....
UPDATE TABLE3 where condn
IF @@ROWCOUNT=0
INSERT TABLE3....
UPDATE TABLE4 where condn
IF @@ROWCOUNT=0
INSERT TABLE4....
不确定这是否可行(问题没有提供足够的信息):
UPDATE TABLE1 where condn
IF @@ROWCOUNT=0
BEGIN
INSERT TABLE1....
INSERT TABLE2....
INSERT TABLE3....
INSERT TABLE4....
END
ELSE
BEGIN
UPDATE TABLE2 where condn
UPDATE TABLE3 where condn
UPDATE TABLE4 where condn
END
【讨论】:
以上是关于delete-insert 与 if-update else-insert 的最佳选择是哪个?的主要内容,如果未能解决你的问题,请参考以下文章