Будет ли выбранный идентификатор из allow_resources(), где id = 1, совпадать с идентификатором, выбранным из ресурсов, где id = 5?
Нет, не будет. Функция PL/pgSQL — это черный ящик для оптимизатора.
Если вы хотите добиться чего-то подобного, используйте функцию language sql
:
CREATE OR REPLACE FUNCTION permitted_resources()
RETURNS TABLE (id int, name varchar(10)) AS
$func$
SELECT r.id, r.name from resources r;
$func$
LANGUAGE sql
stable;
Мы можем проверить это со следующей настройкой:
create table test
(
id integer primary key,
some_nr integer default random() * 1000 + 1,
some_date date default current_date,
some_text text default md5(random()::text)
);
insert into test (id)
select *
from generate_series(1,1e6);
Теперь создайте одну функцию PL/pgSQL:
create function get_data1()
returns setof test
as
$$
begin
return query
select *
from test;
end;
$$
language plpgsql
stable;
И функция SQL:
create function get_data2()
returns setof test
as
$$
select *
from test;
$$
language sql
stable;
Посмотрим, как выглядят планы выполнения:
explain (analyze)
select *
from get_data1() -- this is the PL/pgSQL function
where id = 1234;
Выдает следующий план выполнения:
Function Scan on get_data1 (cost=0.25..4.75 rows=5 width=44) (actual time=261.033..361.218 rows=1 loops=1)
Filter: (id = 1234)
Rows Removed by Filter: 999999
Planning Time: 0.033 ms
Execution Time: 371.302 ms
По-видимому, он сначала извлекает все строки, а затем снова их отбрасывает.
Однако,
explain (analyze)
select *
from get_data2() -- the "SQL" function
where id = 1234;
Выдает следующий план выполнения:
Index Scan using test_pkey on test (cost=0.42..2.43 rows=1 width=45) (actual time=0.015..0.017 rows=1 loops=1)
Index Cond: (id = 1234)
Planning Time: 0.119 ms
Execution Time: 0.031 ms
Эта функция больше не упоминается в плане. Неудивительно, что простой выбор дает тот же план:
explain (analyze)
select *
from test
where id = 1234;
Index Scan using test_pkey on test (cost=0.42..2.43 rows=1 width=45) (actual time=0.014..0.014 rows=1 loops=1)
Index Cond: (id = 1234)
Planning Time: 0.058 ms
Execution Time: 0.026 ms
Я не знаю, верно ли это для более сложных запросов, но простое соединение между такой функцией и другой таблицей показывает такое же поведение.
person
a_horse_with_no_name
schedule
27.08.2020