Używam PostgreSQL 9.2.9 i mam następujący problem.Funkcja PostgreSQL wykonywana znacznie dłużej niż to samo zapytanie
Istnieje funkcja:
CREATE OR REPLACE FUNCTION report_children_without_place(text, date, date, integer)
RETURNS TABLE (department_name character varying, kindergarten_name character varying, a1 bigint) AS $BODY$
BEGIN
RETURN QUERY WITH rh AS (
SELECT (array_agg(status ORDER BY date DESC))[1] AS status, request
FROM requeststatushistory
WHERE date <= $3
GROUP BY request
)
SELECT
w.name,
kgn.name,
COUNT(*)
FROM kindergarten_request_table_materialized kr
JOIN rh ON rh.request = kr.id
JOIN requeststatuses s ON s.id = rh.status AND s.sysname IN ('confirmed', 'need_meet_completion', 'kindergarten_need_meet')
JOIN workareas kgn ON kr.kindergarten = kgn.id AND kgn.tree <@ CAST($1 AS LTREE) AND kgn.active
JOIN organizationforms of ON of.id = kgn.organizationform AND of.sysname IN ('state','municipal','departmental')
JOIN workareas w ON w.tree @> kgn.tree AND w.active
JOIN workareatypes mt ON mt.id = w.type AND mt.sysname = 'management'
WHERE kr.requestyear = $4
GROUP BY kgn.name, w.name
ORDER BY w.name, kgn.name;
END
$BODY$ LANGUAGE PLPGSQL STABLE;
EXPLAIN ANALYZE SELECT * FROM report_children_without_place('83.86443.86445', '14-04-2015', '14-04-2015', 2014);
Razem środowiska wykonawczego: 242805.085 ms. Ale zapytania z ciała funkcja jest wykonywana znacznie szybciej:
EXPLAIN ANALYZE WITH rh AS (
SELECT (array_agg(status ORDER BY date DESC))[1] AS status, request
FROM requeststatushistory
WHERE date <= '14-04-2015'
GROUP BY request
)
SELECT
w.name,
kgn.name,
COUNT(*)
FROM kindergarten_request_table_materialized kr
JOIN rh ON rh.request = kr.id
JOIN requeststatuses s ON s.id = rh.status AND s.sysname IN ('confirmed', 'need_meet_completion', 'kindergarten_need_meet')
JOIN workareas kgn ON kr.kindergarten = kgn.id AND kgn.tree <@ CAST('83.86443.86445' AS LTREE) AND kgn.active
JOIN organizationforms of ON of.id = kgn.organizationform AND of.sysname IN ('state','municipal','departmental')
JOIN workareas w ON w.tree @> kgn.tree AND w.active
JOIN workareatypes mt ON mt.id = w.type AND mt.sysname = 'management'
WHERE kr.requestyear = 2014
GROUP BY kgn.name, w.name
ORDER BY w.name, kgn.name;
Całkowity czas trwania: 2156.740 ms. Dlaczego funkcja jest wykonywana dłużej niż to samo zapytanie? Dziękujemy za
Czy możesz pokazać nam oba plany wykonania? (np. prześlij je do http://explain.depesz.com) –
Jestem nieco uproszczonymi zapytaniami dla lepszej czytelności. Wyjaśnij wynik analizy dla funkcji: http://explain.depesz.com/s/AfeU i dla zapytania: http://explain.depesz.com/s/OKN Poza tym próbuję wyjaśnić w funkcji: http://explain.depesz.com/s/jxnb –
Nie mogę tego teraz znaleźć, ale myślę, że kiedyś przeczytałem, że zapytanie w funkcji jest uruchamiane jako przygotowane zapytanie, co oznacza, że plan jest wykonywany przed poznaniem parametrów, które mogą skutkuje niepoprawnymi planami (ale oszczędza narzutów podczas planowania kwerendy za każdym razem, gdy funkcja jest wykonywana). Jeśli chcesz wykonać zapytanie jako zapytanie dynamiczne za pomocą EXECUTE http://www.postgresql.org/docs/9.2/static/plpgsql-statements.html#PLPGSQL -STATEMENTS-EXECUTING-DYN, plan powinien zostać wykonany, gdy parametry są znany. – Eelke