哪个更好:查询数据库两次或创建一个查询一次的函数

时间:2013-07-03 17:39:59

标签: java postgresql

所以我最近开始使用postgres。而且因为我不能执行“IF else”,除非在一个函数中我很好奇哪个是更好的资源明智和性能明智。 1.创建如下函数来查询存储id的数据库。检查id以查看它是否为null如果是,则else返回id;

CREATE OR REPLACE FUNCTION getallfoo() RETURN INT AS
$BODY$
DECLARE
id INTEGER := (SELECT id FROM foo where (lots of condition checks 15+);
BEGIN
IF id is null then
   INSERT INTO foo(a,b,c,d,e,f) SELECT (1,2,3,4,5,6) RETURNING id INTO id;
   return id;
ELSE 
  RETURN id;
END IF;
END;
$BODY$
Language 'plpgsql';
select * from getallfoo();

或2:首先尝试插入数据库,执行以下操作。接下来查询数据库因为插入失败。我有理由首先进行插入,这不是这个问题的重点。我知道大多数人会先说询问是否存在插入。

INSERT INTO foo (a,b,c,d,e,f, ........, 15+) SELECT (1,2,3,4,5,6, ........., 15+) 
WHERE NOT EXIST(SELECT 1 from foo where a=1, b=2, c=3, up to 15);

因为我在java工作,我只会检查rs.getGeneratedKeys()= 0;如果插入失败,我将重新查询数据库中的id;

SELECT id from foo where a=1, b=2, c=3, ect;

所以问题是因为我的查询中的条件检查很长,最好是创建一个函数并查询数据库一次。或者只是跳过该功能并查询两次。我在大约50个不同的表上进行这些类型的插入。

方面的问题是你可以使用preparedStatement(上面的函数)在java中创建一个函数吗? ResultSet rs = ps.executeUpdate();

2 个答案:

答案 0 :(得分:2)

多次命中数据库,因为不建议使用相同的数据,因为它会降低应用程序的性能。因此,如果您可以在单个函数中执行任务而不是多次查询DB,那么您应该使用函数。

答案 1 :(得分:0)

像往常一样,“它取决于”。

如果你与数据库的连接是低延迟(比如本地主机)那么触发PL / PgSQL过程的开销变得非常重要,启动单独的查询可能会更快。

基准测试,不要猜测。

在这种情况下,我怀疑在PL / PgSQL中这样做会赢,但不是纯粹出于性能原因。您的代码受到多个竞争条件的约束。如果两个人同时运行“getallfoo()”会发生什么?

  1. Tx 1执行INSERT ... WHERE
  2. Tx 2执行INSERT ... WHERE
  3. Tx 1的WHERE条件运行子查询并找不到行
  4. Tx 2的WHERE条件运行子查询并找不到行
  5. Tx 1 INSERT是行
  6. Tx 2 INSERT
  7. Tx 1 COMMIT s并返回ID 1 Tx 2 COMMIT s并返回ID
  8. 如果您对业务密钥有UNIQUE约束(即:不使用生成的主键或也有约束),则第二个INSERT将失败并显示错误。如果不这样做,您将获得该行的两个副本。

    将事情纳入程序并没有帮助;甚至没有一个语句在执行中是原子的。不相关的子查询在外部查询之前运行,等等.MVCC可见性规则通常意味着您没有注意到或关心这一点,但在这种情况下,它们只是意味着您的竞争条件暴露更宽。

    为了正确处理这个问题,你需要一个重试循环,就像在密切相关的upsert example for PL/PgSQL in the documentation中找到的那样。您可以在应用程序或过程中执行此操作,但在过程中执行此操作会显着缩小竞争条件窗口。

    因为您想要一次执行多个键,所以处理起来要复杂得多。您可以举行一次转换尝试选择/插入1 2 3 4 5而其他人需要4 5 6 7 8的比赛。第一个tx将成功插入123 ...然后找到另一个tx已经插入4并在它获得一个时回滚整个更改重复键错误。它不会看到4已经插入,因为第二个tx尚未提交,并且该行将不可见。

    我建议一次执行一个键,或者使用外部过程使用执行错误处理和重试循环的子过程逐个插入每个键。

    所有声音都非常复杂?是的。 PostgreSQL真的可以使用一些内置的SQL扩展来帮助解决这个问题。