попробуйте вот это:
SET search_path = plan_cache_testing;
CREATE TABLE registrations (
id integer NOT NULL PRIMARY KEY,
document_id integer NOT NULL,
reg_date date NOT NULL
);
CREATE INDEX ON registrations(document_id, reg_date);
CREATE OR REPLACE FUNCTION plan_cache_test(arg_id integer, arg_date date)
RETURNS TABLE(id integer, reg_date date)
LANGUAGE plpgsql
STABLE
AS $function$
DECLARE
a_id int;
a_created_at timestamptz;
BEGIN
FOR id, reg_date IN
SELECT r.document_id, r.reg_date
FROM registrations AS r
WHERE r.document_id = arg_id
AND r.reg_date >= arg_date
LOOP
RETURN NEXT;
END LOOP;
RETURN;
END;
$function$
LOAD 'auto_explain';
SET auto_explain.log_analyze = true;
SET auto_explain.log_nested_statements = true;
SET auto_explain.log_timing = true;
SET auto_explain.log_buffers = true;
SET auto_explain.log_triggers = true;
SET auto_explain.log_nested_statements = 't';
SET auto_explain.log_level = 'NOTICE';
SET auto_explain.log_min_duration = 0;
-- 5 times:
SELECT * FROM plan_cache_test(6, '2020-01-01');
SELECT * FROM plan_cache_test(6, '2020-01-01');
SELECT * FROM plan_cache_test(6, '2020-01-01');
SELECT * FROM plan_cache_test(6, '2020-01-01');
SELECT * FROM plan_cache_test(6, '2020-01-01');
-- 6: plan switches to generic/cached:
SELECT *
FROM plan_cache_test(6, '2020-01-01');
-----------------------------------------------------------------------------
-- Imitate session reset on putting it back into the pool:
DISCARD ALL;
-- Let's try again:
SET search_path = plan_cache_testing;
SET auto_explain.log_analyze = true;
SET auto_explain.log_nested_statements = true;
SET auto_explain.log_timing = true;
SET auto_explain.log_buffers = true;
SET auto_explain.log_triggers = true;
SET auto_explain.log_nested_statements = true;
SET auto_explain.log_level = 'NOTICE';
SET auto_explain.log_min_duration = 0;
-- Угадайте, какой план будет здесь?
SELECT *
FROM plan_cache_test(6, '2020-01-02');
Я с телефона, поэтому просто попробую догадаться - он сразу к кешированному плану перейдёт видимо :) Интересно. А для PREPARE/EXECUTE это не работает, потому что PREPARE создаёт новый объект каждый раз, а тут один объект (функция) живёт между сессий. Логично🤔
Обсуждают сегодня