哪个是delete-insert和if-update else-insert的最佳选择?

Vis*_*hal 6 sql-server-2005 query-optimization

更新:

我的不好......我在那些桌子上有一个主键......我的意思是目前没有进一步的索引.在看到性能之后我们可能会在将来看到它,并且由于我们在检索数据时对数据有太多过滤器,因此上次我们运行数据库调优时索引没有显示出太大的改进.

数百万条记录中有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
Run Code Online (Sandbox Code Playgroud)

第二种方式 -

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
Run Code Online (Sandbox Code Playgroud)

现在第二种方式看起来更简单,但可能更耗时......我不确定哪种方式最好.任何人都可以帮助或指导我在这里..谢谢!

gbn*_*gbn 7

如果你期望大多数插入,试试这个

...
BEGIN TRY
   INSERT table1
END TRY
BEGIN CATCH
   IF ERROR_NUMBER = 2627
       UPDATE table1
   ELSE
       --process real error
END CATCH
...
Run Code Online (Sandbox Code Playgroud)

主要是更新......

...
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
...
Run Code Online (Sandbox Code Playgroud)

在高负载下,EXISTS并不足够.如果您要使用EXISTS扫描表,您也可以尝试INSERT.

其他答案:,,

编辑:我称之为JFDI模式......


Tom*_*lak 2

if -exists-then-update-else-insert方法可能比delete-insert需要更多代码,但是(取决于表上定义的索引数量和类型)它对服务器的工作量要少得多。

  • DELETE 或 INSERT 操作需要修改每个索引。
  • UPDATE 操作只需要修改那些在该实例中字段已更新的索引。

因此,除非您通过更新修改记录的每个索引字段,否则越长的方法就越有效。


编辑:您的问题更新表明,目前除了主键(我认为是聚集键)之外,您没有任何索引。所以相比之下:

当该行已经存在时,它是 1 个聚集索引查找(假设您通过 PK 查找记录)并且:

  • 删除-插入:4次写操作(删除行、删除PK索引行、插入行、插入PK索引行)
  • check-update/insert : 1 次写操作(更新行)

当该行尚不存在时,它是 1 个聚集索引查找并且:

  • 删除-插入:2次写操作(插入行、插入PK索引行)
  • check-update/insert:2次写操作(插入行、插入PK索引行)

存在的索引越多,对已存在的行的删除/插入性能就越差。另外,它可能会由于可避免的写入操作而导致非聚集索引变得不必要的碎片。