14.6. Автоподготовленные операторы #

В Postgres Pro Enterprise реализован режим автоподготовки операторов, в котором часто используемые операторы могут неявно подготавливаться, что позволяет оптимизировать затраты на их компиляцию и разбор при каждом последующем выполнении.

По сравнению с применением явно подготовленных операторов, этот режим даёт чуть менее значительное ускорение, но позволяет получать подготовленные планы там, где явные команды PREPARE не поддерживаются. Например, он может быть полезен, когда применяется pgbouncer (в любом режиме, кроме session), когда используются распределённые секционированные таблицы или когда в применяемых приложениях баз данных не предусмотрено выполнение подготовленных операторов.

По умолчанию режим автоподготовки отключён. Чтобы включить его, присвойте ненулевое значение переменной конфигурации autoprepare_threshold, которая определяет, сколько раз должен выполниться оператор, чтобы он был автоматически подготовлен. После того как один запрос с различными буквальными значениями повторяется заданное количество раз, Postgres Pro строит общий план для этого запроса, заменяя все константы параметрами. Общий план для запроса будет выбираться, если ожидаемое время выполнения этого плана окажется меньше, чем среднее время выполнения специализированных планов. Так же, как и с явно подготавливаемыми операторами, при изменениях в каталоге общие планы аннулируются.

Когда эта функциональность включена, автоподготовка может охватывать запросы, передаваемые как по простому, так и по расширенному протоколу. Расширенный протокол поддерживает передачу параметризованных запросов, а автоподготовка таких запросов связана с меньшими издержками. С другой стороны, запросы, поступающие по разным протоколам, могут иметь разный характер, а для некоторых видов запросов автоподготовка неэффективна. В связи с этим параметр autoprepare_for_protocol позволяет включать/отключать автоподготовку операторов на уровне протоколов.

Обратите внимание, что автоподготовка пропускает запросы, содержащие любые указания в комментарии особого вида, который начинается с символов /*+ и заканчивается символами */.

Если ваше приложение выполняет множество различных операторов, в результате автоподготовки они могут занимать много памяти, если не ограничить размер кеша. Это особенно важно при большом количестве активных клиентов, так как кеш автоподготовленных операторов существует в рамках обслуживающего процесса. Чтобы избежать раздувания кеша, вы можете сделать следующее:

  • Ограничить число автоподготавливаемых операторов в рамках одного процесса, воспользовавшись параметром autoprepare_limit. Это рекомендуется, когда нагрузку создаёт множество простых запросов.

  • Ограничить объём памяти, который могут занимать автоподготовленные операторы в обслуживающем процессе, воспользовавшись параметром autoprepare_memory_limit. Это может повлечь некоторые издержки, связанные с вычислением объёма кеша автоподготовленных операторов, поэтому данный вариант рекомендуется только для нагрузки со сложными запросами, когда ограничение количества автоподготовленных операторов может быть неэффективным.

В обоих случаях наиболее часто выполняемые запросы будут находиться в памяти под контролем LRU. Если устанавливаются оба параметра, фактически будет действовать ограничение, которое достигается первым.

Обратите внимание, что кеш автоматически подготовленных операторов полностью очищается при выполнении следующих команд:

  • DISCARD PLANS

  • DISCARD ALL

  • Любая команда ALTER SYSTEM...

  • Любая команда SET var, как отдельная, так и внутри других команд. Например:

    ALTER TABLE test ALTER COLUMN a SET STORAGE PLAIN
  • Любая команда DDL, поддерживающая событийные триггеры, например CREATE/DROP TABLE.

Вы можете просмотреть все автоподготовленные операторы в текущем сеансе, обратившись к системному представлению pg_autoprepared_statements. В нём показывается текст исходного запроса, типы выделенных параметров, заменяющих буквальные значения, и счётчик выполнений запроса.

14.6. Autoprepared Statements #

Postgres Pro Enterprise provides the autoprepare mode that can implicitly prepare frequently used statements to eliminate the cost of their compilation and planning on each subsequent execution.

While providing slightly lower performance gains than explicitly prepared statements, this mode enables you to get prepared plans for cases where explicit PREPARE commands are not supported, such as using pgbouncer with a pooling level other than session, working with distributed partitioned tables, or running database applications that are not designed to execute prepared statements.

By default, the autoprepare mode is switched off. To enable this feature, assign a non-zero value to the autoprepare_threshold configuration variable, which sets the minimal number of times a statement should be executed to get autoprepared. Once the same query with different literal values is repeated the specified number of times, Postgres Pro builds a generic plan for this query, replacing all constant literals with parameters. The generic plan will be chosen for execution if the estimated time of this plan is lower than an average time of the customized plans. Just like for explicitly prepared statements, generic plans get invalidated when a catalog change occurs.

When this feature is enabled, queries submitted via both simple and extended query protocols could be autoprepared. The extended protocol supports the transmission of parameterized queries, and autopreparing of such queries incurs less overhead. On the other hand, queries received via different protocols can be very diverse in nature, and autopreparing is ineffective for some query types. Hence, the autoprepare_for_protocol parameter allows to enable/disable the statement autopreparing on the protocol level.

Note that autopreparing skips queries containing any hints in the special comment that begins with /*+ and ends with */.

If your application issues many different statements, autopreparing them all can cause memory overflow unless you impose any cache restrictions. It is especially important when running multiple active clients as the cache of autoprepared statements is local to the backend. To avoid cache bloat, you can do the following:

  • Limit the number of autoprepared statements per backend using the autoprepare_limit parameter. This setting is recommended for workloads with multiple simple queries.

  • Limit the amount of memory that can be allocated for autoprepared statements on a backend using the autoprepare_memory_limit parameter. This setting can incur some overhead when calculating the amount of cache used for autoprepared statements, so it is only recommended for workloads that contain complex queries for which limiting the number of autoprepared statements may be ineffective.

In both cases, most frequently used queries are kept in memory using the LRU strategy. If both parameters are set, Postgres Pro enforces the first reached limit.

Note that the cache of autoprepared statements is fully cleaned up when executing the following commands:

  • DISCARD PLANS

  • DISCARD ALL

  • Any ALTER SYSTEM... command

  • Any SET var command, both standalone and and inside other commands. For example:

    ALTER TABLE test ALTER COLUMN a SET STORAGE PLAIN
    

  • Any DDL command that supports event triggers, such as CREATE/DROP TABLE

You can check all autoprepared statements available in the current session in the pg_autoprepared_statements system view. It shows the original text of the query, types of the extracted parameters that replace literals, and the query execution counter.

FAQ