我有以下函数,我想在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
)
函数has_access(id,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$
但是现在我在函数中的一个表上只有一个子查询,这在我的情况下没用。有关如何正确执行此操作以避免遇到性能问题的任何建议吗?
谢谢!
答案 0 :(得分:0)
好的,我想我知道你的问题是什么;函数调用不可优化,因此需要在函数外部进行查询;
之类的东西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)