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



所以我最近开始使用postgres。由于我不能执行"IF else",除非在某个函数中,我很好奇资源和性能哪个更好。1.创建如下函数来查询存储id的数据库。如果是,请检查id是否为null。否则,请插入并返回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();

对于相同的数据多次访问数据库是不可取的,因为这会降低应用程序的性能。所以,若您可以在单个函数中执行任务,而不是多次查询DB,那个么您应该使用函数。

和往常一样,"这取决于"。

如果您与数据库的连接是低延迟的(比如说本地主机),那么启动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 s该行
  6. Tx 2 INSERT s该行
  7. Tx 1 COMMIT s并返回ID1 Tx 2 COMMIT s并返回ID

如果您对业务密钥有UNIQUE约束(即:不使用生成的主键或也有约束),则第二个INSERT将失败并出现错误。如果你不这样做,你会得到两份这一行的副本。

把事情放在程序中没有帮助;甚至没有一个语句在执行中是原子的。不相关的子查询在外部查询之前运行,等等。MVCC可见性规则通常意味着你没有注意到或关心这一点,但在这种情况下,它们只是意味着你的种族条件暴露范围有点广。

要正确处理此问题,您需要一个重试循环,如文档中与PL/PgSQL密切相关的upstart示例中所示。您可以在应用程序或过程中执行此操作,但在过程中执行该操作会显著缩小竞争条件窗口。

因为要同时执行多个关键点,所以处理起来要复杂得多。在比赛中,一个transition试图选择/插入1 2 3 4 5,而另一个transaction想要4 5 6 7 8。第一个tx将成功插入123。。。然后发现另一个tx已经插入了CCD_ 16,并且当它得到重复密钥错误时回滚整个更改。它不会看到4已经插入,因为第二个tx还没有提交,行也不可见。

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

所有这些听起来都很复杂?是的。PostgreSQL确实可以使用一些内置的SQL扩展来帮助实现这一点。

相关内容

  • 没有找到相关文章

最新更新