插入失败然后更新或加载,然后决定是否插入或更新

时间:2008-12-19 15:54:23

标签: java database performance

我在java中有一个web服务,它接收要在数据库中插入或更新的信息列表。我不知道要插入或更新哪一个。

哪一种是获得更好性能结果的最佳方法:

  1. 迭代列表(对象列表,其上有表pk),尝试在数据库中插入条目。如果插入失败,请运行更新

  2. 尝试从数据库加载条目。如果结果检索更新,如果没有插入条目。

  3. 另一种选择?告诉我它:)

  4. 在第一次通话中,我相信大多数参赛作品都是新的参赛作品,但是会有一个饱和点,大多数参赛作品将会更新。

    我说的是一个数据库表,它可以以成熟的形式达到1亿多个条目。

    你的方法是什么?表现是我​​最重要的目标。

5 个答案:

答案 0 :(得分:4)

如果您的数据库支持MERGE,我认为这是最有效的(并将所有数据视为一组)。

请参阅:

http://www.oracle.com/technology/products/oracle9i/daily/Aug24.html

https://web.archive.org/web/1/http://blogs.techrepublic%2ecom%2ecom/datacenter/?p=194

答案 1 :(得分:1)

如果表现是你的目标,那么首先要从你的词汇中删除单词iterate!学会做套装。

如果您需要更新或插入,请始终先进行更新。否则很容易发现你自己更新了刚插入的记录。如果您这样做,有助于获得一个标识符,您可以查看该记录是否存在。如果标识符存在,则执行更新,否则执行插入。

答案 2 :(得分:1)

重要的是要了解插入数量与您收到的列表中的更新数量之间的平衡或比率。恕我直言,你应该实现一个抽象的策略,说“在数据库上坚持这个”。然后创建具体策略(例如):

  1. 检查主键,如果找到零记录,则插入,否则更新
  2. 更新,如果失败,是否插入。
  3. 他人
  4. 然后从配置文件中提取要使用的策略(例如,类完全限定名称)。这样您就可以轻松地从一种策略切换到另一种策略。如果可行,可能取决于您的域,您可以根据集合上的输入实体设置一个启发式选择最佳策略。

答案 3 :(得分:1)

MySQL支持:

INSERT INTO foo
SET bar='baz', howmanybars=1
ON DUPLICATE KEY UPDATE howmanybars=howmanybars+1

答案 4 :(得分:1)

选项2不会是最有效的。当您执行实际插入或更新以强制执行主键时,数据库将已经为您进行此检查。通过自己进行此检查,您将承担两次表查找的开销以及来自Java代码的额外往返。选择最有可能的案例和乐观的代码。

扩展选项1,您可以使用存储过程来处理插入/更新。这个使用PostgreSQL语法的例子假设插入是正常情况。

CREATE FUNCTION insert_or_update(_id INTEGER, _col1 INTEGER) RETURNS void
AS $$
    BEGIN
        INSERT INTO
            my_table (id, col1)
        SELECT
            _id, _col1;
    EXCEPTION WHEN unique_violation THEN
        UPDATE
            my_table
        SET
            col1 = _col1
        WHERE
            id = _id;
    END;
END;
$$
LANGUAGE plpgsql;

您还可以使更新成为正常情况,然后检查受update语句影响的行数,以确定该行是否实际是新的并且您需要执行插入操作。

在其他一些答案中提到,处理此操作的最有效方法是一批:

  1. 获取传递给Web服务的所有行,并将它们批量插入临时表
  2. 从临时表
  3. 更新mater表中的行
  4. 从临时表
  5. 在主表中插入新行
  6. 处理临时表
  7. 要使用的临时表的类型和最有效的管理方式取决于您使用的数据库。