【发布时间】:2014-11-03 21:54:12
【问题描述】:
我想在 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 子句。实际上,与以下查询相比,该查询非常慢(内联 EXISTS 子句而没有 SELECT 子句):
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$
但现在我在函数的一张表上只有一个子查询,这对我来说没有用。有关如何正确执行此操作以免遇到性能问题的任何建议?
谢谢!
【问题讨论】:
-
EXISTS 往往会导致相关子查询,这对 DBMS 来说更难优化;使用 IN/NOT IN 往往更有效。
-
@okaram:完全错误。请注意,在这种情况下没有相关的子查询,因为没有主查询。
-
@wildplasser,函数中的查询是不相关的,但上面那个是(但我在发表评论时不明白问题是函数:)
标签: function postgresql plpgsql inline-code