Я полагаю, это потому, что pg_sleep является изменчивой функцией. Когда вы запрашиваете представление, вы действуете так:
select id from (select id, pg_sleep(0.001)::text from administrative_areas) order by id desc limit 1;
Postgres видит эту изменчивую функцию в подзапросе и запускает ее для каждой строки. Давайте проверим это.
create table test as select id from generate_series(1, 1000) g(id);
create index on test(id);
analyze test;
create view sleepy as select id, pg_sleep(0.001)::text from test;
explain analyze select * from sleepy order by id desc limit 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Limit (cost=37.50..37.50 rows=1 width=36) (actual time=1640.368..1640.439 rows=1 loops=1)
-> Sort (cost=37.50..40.00 rows=1000 width=36) (actual time=1640.336..1640.358 rows=1 loops=1)
Sort Key: test.id DESC
Sort Method: top-N heapsort Memory: 25kB
-> Seq Scan on test (cost=0.00..22.50 rows=1000 width=36) (actual time=1.511..1623.058 rows=1000 loops=1)
Planning Time: 0.175 ms
Execution Time: 1640.617 ms
(7 rows)
Это запустило pg_sleep для каждой строки в тесте, как и ожидалось.
Теперь попробуйте стабильную функцию:
create function not_so_sleepy()
returns void AS
$$
select pg_sleep(0.001)
$$ language sql
stable; -- NOTE: this is just to trick postgres
create view not_as_sleepy as
select id,
not_so_sleepy()::text
FROM test;
explain analyze select *
from not_as_sleepy
order by id desc limit 1;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.28..0.32 rows=1 width=36) (actual time=0.049..0.198 rows=1 loops=1)
-> Index Only Scan Backward using test_id_idx on test (cost=0.28..43.27 rows=1000 width=36) (actual time=0.024..0.048 rows=1 loops=1)
Heap Fetches: 1
Planning Time: 1.786 ms
Execution Time: 0.308 ms
(5 rows)
Во втором случае мы сказали postgres, что эта функция не будет иметь побочных эффектов, поэтому она могла бы ее игнорировать. Таким образом, функция должна быть помечена как стабильная или неизменная (и, конечно, она должна быть фактически стабильной / неизменной), чтобы postgres не беспокоил ее выполнение.