F.61. sr_plan

Важно

Поддержка расширения sr_plan в Postgres Pro прекращена.

F.61.1. Обоснование

Расширение sr_plan позволяет сохранять планы выполнения запросов и использовать эти планы при последующем выполнении тех же запросов, исключая многократную оптимизацию одного и того же запроса.

Модуль sr_plan действует подобно системе Oracle Outline. Используя его, вы можете жёстко зафиксировать план выполнения. Это бывает необходимо, если вы уверены, что планировщик не сможет выработать лучший план.

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

Затем сохранённые планы должны задействоваться приложением, выполняющим эти запросы.

F.61.2. Установка

Выполните в вашей базе:

CREATE EXTENSION sr_plan;

И отредактируйте postgresql.conf:

shared_preload_libraries = 'sr_plan'

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

F.61.3. Использование

Если вы хотите сохранить план запроса, необходимо установить переменную:

set sr_plan.write_mode = true;

После этого планы всех последующих запросов будут сохраняться в таблице sr_plans, пока этой переменной не будет присвоено значение false. Помните, что при этом сохраняются планы всех запросов, включая повторные. Выполните нужный вам запрос:

select query_hash from sr_plans where query_hash=10;

Отключите сохранение планов:

set sr_plan.write_mode = false;

Убедитесь в том, что план запроса сохранён:

select query_hash, enable, valid, query, explain_jsonb_plan(plan) from sr_plans;

 query_hash | enable | valid |                        query                         |                 explain_jsonb_plan                 
------------+--------+-------+------------------------------------------------------+----------------------------------------------------
 1783086253 | f      | t     | select query_hash from sr_plans where query_hash=10; | Bitmap Heap Scan on sr_plans                      +
            |        |       |                                                      |   Recheck Cond: (query_hash = 10)                 +
            |        |       |                                                      |   ->  Bitmap Index Scan on sr_plans_query_hash_idx+
            |        |       |                                                      |         Index Cond: (query_hash = 10)             +
            |        |       |                                                      | 

Обратите внимание на вызов функции explain_jsonb_plan, которая позволяет визуализировать план выполнения подобно тому, как это делает команда EXPLAIN.

Планы сохраняются в базе данных в виде jsonb. По умолчанию все записанные планы отключены, их использование необходимо разрешить вручную:

Чтобы разрешить использование сохранённого плана, выполните:

update sr_plans set enable=true where query_hash=1783086253;

(Здесь 1783086253 указано только для примера.) После этого при выполнении данного запроса будет использоваться план из таблицы sr_plans.

Кроме того, sr_plan позволяет сохранять планы параметризованных запросов. В этом случае в запросе будут некоторые константы, которые, как предполагается, не должны влиять на план.

Мы можем пометить в режиме сохранения плана эти константы как параметры запроса, используя специальную функцию _p (anyelement). Например:

=>create table test_table (a numeric, b text);
CREATE TABLE
=>insert into test_table values (1,'1'),(2,'2'),(3,'3');
INSERT 0 3 
=> set sr_plan.write_mode = true;
SET
=> select a,b  from test_table where a = _p(1);
 a | b
---+---
 1 | 1
(1 row)

=> set sr_plan.write_mode = false;
SET

Теперь план запроса к нашей таблице сохранён с параметром. И если мы включим сохранённый план, он будет использоваться для запросов с любым значением a, если это значение будет завёрнуто в вызов функции _p().

=>update sr_plans set enable = true where query=
  'select a,b from test_table where a = _p(1)';
UPDATE 1
-- Эти запросы будут использовать сохранённый план

=>select a,b from test_table where a = _p(2);
 a | b
---+---
 2 | 2
(1 row)

=>select a,b from test_table where a = _p(3);
 a | b
---+---
 3 | 3
(1 row)

-- Этот запрос не будет использовать сохранённый план, так как
-- константа не завёрнута в _p()

=>select a,b from test_table where a = 1;
 a | b
---+---
 1 | 1
(1 row)

F.61. sr_plan

Important

The sr_plan extension is no longer supported in Postgres Pro.

F.61.1. Rationale

sr_plan is an extension which allows to save query execution plans and use these plans for all repetitions of same query, instead of optimizing identical query again and again.

sr_plan looks like Oracle Outline system. It can be used to lock the execution plan. It is necessary if you do not trust the planner or able to form a better plan.

Typically, DBA would play with queries interactively, and save their plans and then enable use of saved plans for the queries, where predictable response time is essential.

Then application which uses these queries would use saved plans.

F.61.2. Installation

In your db:

CREATE EXTENSION sr_plan;

and modify your postgresql.conf:

shared_preload_libraries = 'sr_plan'

It is essential that library is preloaded during server startup, because use of saved plans is enabled on per-database basis and doesn't require any per-connection actions.

F.61.3. Usage

If you want to save the query plan is necessary to set the variable:

set sr_plan.write_mode = true;

Now plans for all subsequent queries will be stored in the table sr_plans, until this variable is set to false. Don't forget that all queries will be stored including duplicates. Making an example query:

select query_hash from sr_plans where query_hash=10;

Disable saving the query:

set sr_plan.write_mode = false;

Now verify that your query is saved:

select query_hash, enable, valid, query, explain_jsonb_plan(plan) from sr_plans;

 query_hash | enable | valid |                        query                         |                 explain_jsonb_plan                 
------------+--------+-------+------------------------------------------------------+----------------------------------------------------
 1783086253 | f      | t     | select query_hash from sr_plans where query_hash=10; | Bitmap Heap Scan on sr_plans                      +
            |        |       |                                                      |   Recheck Cond: (query_hash = 10)                 +
            |        |       |                                                      |   ->  Bitmap Index Scan on sr_plans_query_hash_idx+
            |        |       |                                                      |         Index Cond: (query_hash = 10)             +
            |        |       |                                                      | 

Note use of explain_jsonb_plan function, that allows you to visualize execution plan in the similar way as EXPLAIN command does.

In the database plans are stored as jsonb. By default, all the newly saved plans are disabled, you need enable it manually:

To enable use of the saved plan

update sr_plans set enable=true where query_hash=1783086253;

(1783086253 for example only) After that, the plan for the query will be taken from the sr_plans table.

In addition sr plan allows you to save a parameterized query plan. In this case, we have some constants in the query that, as we know, do not affect plan.

During plan saving mode we can mark these constants as query parameters using a special function _p (anyelement). For example:

=>create table test_table (a numeric, b text);
CREATE TABLE
=>insert into test_table values (1,'1'),(2,'2'),(3,'3');
INSERT 0 3 
=> set sr_plan.write_mode = true;
SET
=> select a,b  from test_table where a = _p(1);
 a | b
---+---
 1 | 1
(1 row)

=> set sr_plan.write_mode = false;
SET

Now plan for query from our table is saved with parameter. So, if we enable saved plan in this table, this plan would be used for query with any value for a, as long as this value is wrapped with _p() function.

=>update sr_plans set enable = true where query=
  'select a,b from test_table where a = _p(1)';
UPDATE 1
-- These queries would use saved plan

=>select a,b from test_table where a = _p(2);
 a | b
---+---
 2 | 2
(1 row)

=>select a,b from test_table where a = _p(3);
 a | b
---+---
 3 | 3
(1 row)

-- This query wouldn't use saved plan, because constant is not wrapped
-- with _p()

=>select a,b from test_table where a = 1;
 a | b
---+---
 1 | 1
(1 row)