Назад | Перейти на главную страницу

Необработанный запрос PostgreSQL против «Функция возвращает ТАБЛИЦУ» - безумная разница в производительности. Зачем?

Я работаю с PostgreSQL, и он используется для отчетности. В настоящее время он настроен следующим образом:

Существует сложный запрос, который возвращает данные отчета, например:

select Column1 as Name1, Column2 as Name2
from sometable tbl
inner join ...
where ...
and ...
and $1 <= somedate
and $2 >= somedate
group by ...
order by ...;

Есть функция, которая использует этот запрос и определена так

CREATE OR REPLACE FUNCTION GetMyReport(IN fromdate timestamp without time zone, IN todate timestamp without time zone)
  RETURNS TABLE(Name1 character varying, Name2 character varying) AS
$BODY$

--query start
select Column1 as Name1, Column2 as Name2
from sometable tbl
inner join ...
where ...
and ...
and $1 <= somedate
and $2 >= somedate
group by ...
order by ...;
--query end

$BODY$
  LANGUAGE sql VOLATILE
  COST 10
  ROWS 1000;

Наконец, когда приложение для создания отчетов вызывает функцию, оно отправляет следующий SQL:

select null::text as Name1, Name2 from GetMyReport ('2012-05-28T12:19:39.0000000+11:00'::timestamp, '2012-05-28T12:19:44.0000000+11:00'::timestamp);

И моя проблема:

В чем может быть причина?

Хорошо, это было легко. Оказывается, база данных должна подготовить план запроса до того, как узнает о параметрах, что приводит к плохим результатам. Решением было использовать plpgsql и вернуть QUERY EXECUTE. Теперь производительность такая же, как и ожидалось.

CREATE OR REPLACE FUNCTION GetMyReport(IN fromdate timestamp without time zone, IN todate timestamp without time zone)
  RETURNS TABLE(Name1 character varying, Name2 character varying) AS
$BODY$

BEGIN
RETURN QUERY EXECUTE'
select Column1 as Name1, Column2 as Name2
from sometable tbl
inner join ...
where ...
and ...
and $1 <= somedate
and $2 >= somedate
group by ...
order by ...;' USING $1, $2
END

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 10
  ROWS 1000;