Function 函数中EXISTS子句的性能不佳

Function 函数中EXISTS子句的性能不佳,function,postgresql,plpgsql,inline-code,Function,Postgresql,Plpgsql,Inline Code,我想在sql查询Postgres 9.3中使用以下函数: SELECT * FROM test_table tt WHERE has_access(tt.id, tt.login) CREATE OR REPLACE FUNCTION has_access(integer, integer) RETURNS boolean AS $BODY$ SELECT EXISTS (SELECT true FROM test_read_access WHE

我想在sql查询Postgres 9.3中使用以下函数:

SELECT * FROM test_table tt WHERE has_access(tt.id, tt.login)

CREATE OR REPLACE FUNCTION has_access(integer, integer)
RETURNS boolean AS
$BODY$
SELECT
  EXISTS (SELECT true
            FROM test_read_access
          WHERE id = $1 and login = $2 
  )
  AND
  NOT EXISTS (SELECT true
            FROM test_no_read_access
          WHERE id = $1 and login = $2 
  )
$BODY$
只要我只关心函数的正确性,这就行了。因为查询分析器告诉我,必须为每一行计算函数,因此不能按预期优化EXISTS子句。实际上,与以下不包含SELECT子句而内联EXISTS子句的查询相比,查询速度非常慢:

SELECT * FROM test_table tt WHERE 
   EXISTS (SELECT true
            FROM test_read_access
          WHERE id = tt.id and login = tt.login 
  )
  AND
  NOT EXISTS (SELECT true
            FROM test_no_read_access
          WHERE id = tt.id and login = tt.login 
  )
该函数的目的是拥有_accessid,login是将函数中的一些访问规则分组,然后在不同的查询中使用它。我的意思是,这样做可以获得良好的性能:

SELECT * FROM test_table tt WHERE EXISTS (select has_access(tt.id, tt.login))

CREATE OR REPLACE FUNCTION has_access(integer, integer)
RETURNS SETOF boolean AS
$BODY$
SELECT true
   FROM test_read_access
WHERE id = $1 and login = $2 
$BODY$
但是现在我在函数中的一个表上只有一个子查询,这在我的例子中没有用处。有没有关于如何正确执行此操作以避免出现性能问题的建议


谢谢

好吧,我想我明白你的问题所在了;函数调用不可优化,因此需要在函数外部执行查询;差不多

SELECT *
  FROM test_table
WHERE (id,login) IN (SELECT id,login FROM test_read_access)
  AND (id,login) NOT IN (SELECT id,login FROM test_no_read_access)

Check

EXISTS倾向于导致相关子查询,这对于DBMS来说更难优化;在中/不在中使用往往更有效。@okaram:完全错误。请注意,在这种情况下,没有相关的子查询,因为没有主查询。@wildplasser,函数中的查询没有相关,但上面的查询是,但我不知道问题出在我发表评论时的函数上:没有理由不选择在。。。在这里不存在。。。同样有效,甚至更好。OQ中的性能问题在于函数调用,这是Optimizer无法解决的。@wildplasser我现在明白问题在于函数调用;但是,通常in/notin查询更容易优化,对吗?EXISTS倾向于做相关子查询需要引用查询内的外行,这对优化器来说比较困难。在过去几年中,我在Postgres中进行了大量的测试,结果表明,NOT EXISTS比NOT in更快。此外,NOT In在使用空值时表现出棘手的行为。即将到来的第9.4页可能会有变化。不说有,也不期待。只是还没有测试。