Which is better: Query database twice or create a function to query once
所以我最近开始使用postgres。而且因为我不能执行"IF else",除非在一个函数中我很好奇哪个是更好的资源明智和性能明智。 1.创建如下函数来查询存储id的数据库。检查id是否为null,如果是,则执行insert else返回id;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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:首先尝试插入数据库,执行以下操作。接下来查询数据库因为插入失败。我有理由首先进行插入,这不是这个问题的重点。我知道大多数人会先说询问是否存在插入。
1 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;
1 | SELECT id from foo where a=1, b=2, c=3, ect; |
所以问题是因为我的查询中的条件检查是冗长的,最好是创建一个函数并查询数据库一次。或者只是跳过该功能并查询两次。我在大约50个不同的表上进行这些类型的插入。
可以使用preparedStatement(上面的函数)在java中创建一个函数
ResultSet rs = ps.executeUpdate();
多次命中数据库,因为不建议使用相同的数据,因为它会降低应用程序的性能。因此,如果您可以在单个函数中执行任务而不是多次查询DB,那么您应该使用函数。
像往常一样,"它取决于"。
如果你与数据库的连接是低延迟(比如本地主机)那么触发PL / PgSQL过程的开销变得非常简单,启动单独的查询可能会更快。
基准,不要猜。
在这种情况下,我怀疑在PL / PgSQL中这样做会赢,但不是纯粹出于性能原因。您的代码受多种竞争条件的制约。如果两个人同时运行"getallfoo()"会发生什么?
1 Tx 2
如果您对业务键具有
将事情纳入程序并没有帮助;甚至没有一个语句在执行中是原子的。不相关的子查询在外部查询之前运行,等等.MVCC可见性规则通常意味着您没有注意到或关心这一点,但在这种情况下,它们只是意味着您的竞争条件暴露有点宽。
要正确处理这个问题,你需要一个重试循环,就像在文档中与PL / PgSQL密切相关的upsert示例中所发现的那样。您可以在应用程序或过程中执行此操作,但在过程中执行此操作应显着缩小竞争条件窗口。
因为您想要一次执行多个键,所以处理起来要复杂得多。您可以在一个转换尝试选择/插入
我建议一次做一个密钥,或者使用一个外部过程,使用执行错误处理和重试循环的子过程逐个插入每个密钥。
一切听起来都很复杂吗?是的。 PostgreSQL真的可以使用一些内置的SQL扩展来帮助解决这个问题。