Which is the best choice in delete-insert vs if-update else-insert?

泪湿孤枕 提交于 2019-12-04 06:06:02

The if-exists-then-update-else-insert approach may be more code than delete-insert, but (depending on how many and what kind of indexes are defined on the tables) it is a lot less work for the server.

  • A DELETE or INSERT operation requires every index to be modified, period.
  • An UPDATE operation only requires these indexes modified whose fields have been updated in this instance.

So unless you modify every indexed field of the record with your updates, the longer approach is the more efficient one.


EDIT: Your question update says that currently you do not have any indexes apart from the primary key (which I assume is a clustered key). So in comparison:

When the row already exists, it's 1 clustered index seek (assuming you find records by their PK) and:

  • delete-insert: 4 write operations (delete row, delete PK index row, insert row, insert PK index row)
  • check-update/insert: 1 write operation (update row)

When the row does not yet exist, it's 1 clustered index seek and:

  • delete-insert: 2 write operations (insert row, insert PK index row)
  • check-update/insert: 2 write operations (insert row, insert PK index row)

The more indexes exist, the worse will delete/insert perform for rows that already exist. Plus it can cause non-clustered indexes to become unnecessarily fragmented due to avoidable write operations.

gbn

If you expect mostly inserts, try this

...
BEGIN TRY
   INSERT table1
END TRY
BEGIN CATCH
   IF ERROR_NUMBER = 2627
       UPDATE table1
   ELSE
       --process real error
END CATCH
...

Mostly updates...

...
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 isn't concurrent enough under high loads. If you are going to scan the table with EXISTS, you may as well just try the INSERT anyway.

Other answers: One, Two, Three

Edit: I call this the JFDI pattern...

try this:

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....

not sure if this would work (question does not provide enough info):

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!