Обновление в PostgreSQL 9.2
Произошло значительное улучшение, я цитирую примечания к выпуску здесь :
Разрешить планировщику для создания пользовательских планов для конкретного параметра
значения даже при использовании подготовленных высказываний (Том Лейн)
В прошлом у подготовленного заявления всегда был один "общий" план
который был использован для всех значений параметров, что часто было много
уступает планам, используемым для неподготовленных заявлений, содержащих
явные значения констант. Теперь планировщик пытается создать пользовательский
планы для конкретных значений параметров. Общий план будет использоваться только
после пользовательских планов неоднократно доказано, что не дают никакой пользы. это
изменение должно устранить штрафы за производительность, ранее замеченные из
использование подготовленных высказываний (включая нединамические высказывания в
PL / PgSQL). * * 1 010
Оригинальный ответ для PostgreSQL 9.1 или старше
Функции plpgsql имеют тот же эффект, что и оператор PREPARE
: запросы анализируются, а план запроса кэшируется.
Преимущество заключается в том, что некоторые затраты сохраняются для каждого вызова.
Недостатком является то, что план запроса не оптимизирован для конкретных значений параметров, с которыми он вызывается.
Для запросов к таблицам с равномерным распределением данных это, как правило, не представляет проблемы, и функции PL / pgSQL будут работать несколько быстрее, чем необработанные запросы SQL или функции SQL. Но если ваш запрос может использовать определенные индексы в зависимости от фактических значений в предложении WHERE
или, в более общем случае, выбрать лучший план запроса для определенных значений, вы можете получить неоптимальный план запроса. Попробуйте использовать функцию SQL или используйте динамический SQL с EXECUTE
, чтобы принудительно перепланировать запрос для каждого вызова. Может выглядеть так:
CREATE OR REPLACE FUNCTION pie(id_param integer)
RETURNS SETOF record AS
$BODY$
BEGIN
RETURN QUERY EXECUTE
'SELECT *
FROM table_name
where id = $1'
USING id_param;
END
$BODY$
LANGUAGE plpgsql STABLE;
Редактировать после комментария:
Если этот вариант не меняет время выполнения, должны быть и другие факторы, которые вы могли пропустить или не упомянуть. Другая база данных? Разные значения параметров? Вы должны будете опубликовать более подробную информацию.
Я добавляю цитату из руководства , чтобы поддержать мои приведенные выше утверждения:
EXECUTE с простой константой командной строки и некоторым ИСПОЛЬЗОВАНИЕМ
Параметры, как в первом примере выше, функционально эквивалентны
просто написать команду прямо в PL / pgSQL и позволить
замена переменных PL / pgSQL происходит автоматически.
Важным отличием является то, что EXECUTE будет перепланировать команду на каждом
выполнение, генерация плана, который является специфическим для текущего параметра
ценности; тогда как PL / pgSQL обычно создает общий план и кэширует его
для повторного использования. В ситуациях, когда лучший план сильно зависит от
значения параметров EXECUTE могут быть значительно быстрее; в то время как когда
план не чувствителен к значениям параметров, перепланирование будет
отходы.