# Занятие 13: Производительность / Отчеты по нагрузке pgpro_pwr

> Исходная страница в нативном Markdown: Производительность / Отчеты по нагрузке pgpro_pwr

---

Индекс LLMS: [llms.txt](/ru/llms.txt)

---

<!-- Generated by scripts/generate_skeleton.py. -->

> [!NOTE]
> Эта страница извлечена из официального PDF в нативный Markdown. Текст слайдов, код и комментарии сохранены в порядке чтения; исходные PDF и HTML остаются эталоном макета.
> **HTML source:** [pgpro_13_pwr.html](https://edu.postgrespro.ru/16/pgpro-16/pgpro_13_pwr.html)
> **Archive:** [PGPRO-handouts-16.zip](https://edu.postgrespro.ru/16/PGPRO-handouts-16.zip)
> **Страниц PDF:** 23

## Page 1: Производительность / Отчеты по нагрузке pgpro_pwr {#source-page-001}

### Авторские права

© Postgres Professional, 2023–2026 Авторы: Алексей Береснев, Илья Баштанов, Павел Толмачев, Игорь Гнатюк Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)
### Использование материалов курса

Некоммерческое использование материалов курса (презентации, демонстрации) разрешается без ограничений. Коммерческое использование возможно только с письменного разрешения компании Postgres Professional. Запрещается внесение изменений в материалы курса.
### Обратная связь

Отзывы, замечания и предложения направляйте по адресу: edu@postgrespro.ru
### Отказ от ответственности

Компания Postgres Professional не несет никакой ответственности за любые повреждения и убытки, включая потерю дохода, нанесенные прямым или непрямым, специальным или случайным использованием материалов курса. Компания Postgres Professional не предоставляет каких-либо гарантий на материалы курса. Материалы курса предоставляются на основе принципа «как есть» и компания Postgres Professional не обязана предоставлять сопровождение, поддержку, обновления, расширения и изменения.

## Page 2: Темы {#source-page-002}

- Обзор pgpro\_pwr
- Архитектура pgpro\_pwr
- Установка pgpro\_pwr
- Выборки
- Политика хранения
- Выборочные линии
- Размеры отношений
- Отчеты

## Page 3: Обзор pgpro_pwr {#source-page-003}

**Расширение для выявления ресурсоемких операций в БД**
  - поиск запросов, потребляющих много ресурсов
  - определение характера и интенсивности нагрузки
  - анализ исторической информации о нагрузке
  - сравнение профилей нагрузки
  - помощь в расследовании инцидентов

### Комментарии преподавателя

Расширение pgpro\_pwr предназначено для выявления наиболее ресурсоемких операций в базе данных. PWR произносится как «пауэр» (power) — это сокращение от Postgres Pro Workload Reporting.

Расширение основано на pg\_profile — расширении с открытым исходным кодом для PostgreSQL:

<https://github.com/zubkov-andrei/pg\_profile>

Предназначение:

● поиск запросов, потребляющих больше всего ресурсов СУБД;

● получение информации о типе и интенсивности нагрузки;

● исследование нагрузки на «горячие» объекты;

● сохранение и анализ нагрузки в историческом разрезе;

● сравнение профилей нагрузки, имевших место в разное время;

● облегчение расследования инцидентов;

● проведение анализа нагрузочного тестирования.

Основная идея расширения — сохранение снимков собранных данных для последующего анализа.

Документация:

<https://postgrespro.ru/docs/enterprise/16/pgpro-pwr>

## Page 4: Архитектура pgpro_pwr {#source-page-004}

![Source slide page 4: Архитектура pgpro_pwr](images/page-004.png){#source-figure-004 caption="Source slide page 4: Архитектура pgpro_pwr"}

**Статистика собирается с целевых серверов расширениями pgpro\\\_stats или pg\\\_stat\\\_statements**
- Выборки-снимки помещаются в репозиторий истории
- По выборкам создаются отчеты об изменениях

### Комментарии преподавателя

Исходные данные собираются с целевых серверов с помощью представлений сборщика статистики и расширения pgpro\_stats или pg\_stat\_statements. Рекомендуется использовать расширение pgpro\_stats, так как оно выдает планы операторов, информацию о событиях ожидания и нагрузке по отдельным базам данных, ролям, клиентам и приложениям. Сводная статистика ожиданий поступает от расширения pg\_wait\_sampling. Если нет возможности использовать pgpro\_stats, можно использовать pg\_stat\_kcache как источник информации об использовании ресурсов процессора и о нагрузке на файловую систему (rusage).

Работа модуля pgpro\_pwr заключается в обработке накапливаемых статистических выборок. Выборка содержит статистику о наиболее активных объектах и запросах, собранную с момента получения предыдущей выборки. По выборкам строят отчеты.

Расширение pgpro\_pwr состоит из следующих частей:

● репозиторий истории — хранилище собранных данных;

● механизм управления выборками — предоставляет функции для получения выборок и поддержки репозитория в актуальном состоянии посредством удаления устаревших данных;

● механизм отчетов — представляет функции построения отчетов по данным из репозитория;

● административные функции для создания серверов, линий выборок и для управления ими.

## Page 5: Установка pgpro_pwr {#source-page-005}

**Пакет pgpro\\\_pwr устанавливается средствами ОС**
- Упрощенная установка
  - pgpro\_pwr непосредственно на целевом сервере,
  - отслеживание нагрузки от имени суперпользователя
- Развернутая установка
  - нагрузка отслеживается на одном или нескольких удаленных серверах
  - от имени специально зарегистрированного пользователя

### Комментарии преподавателя

Предполагается, что уже установлено расширение pgpro\_stats или pg\_stat\_statements и настроен сборщик статистики Postgres Pro.

Само расширение pgpro\_pwr собрано в отдельный установочный пакет и по умолчанию не устанавливается.

Упрощенная установка предназначена для случаев, когда pgpro\_pwr устанавливается непосредственно на целевой сервер и будет отслеживать его нагрузку от имени суперпользователя. Она сводится к созданию отдельной схемы для объектов расширения и установке расширения. Так как pgpro\_pwr зависит от расширения dblink, то либо в команду CREATE EXTENSION добавляют ключевое слово CASCADE, либо устанавливают dblink заранее.

Развернутая установка должна выполняться, когда планируется использовать pgpro\_pwr для отслеживания нагрузки на одном или нескольких серверах с соблюдением принципа наименьших привилегий.

Описание вариантов установки в документации: <https://postgrespro.ru/docs/enterprise/16/pgpro-pwr#PGPRO-PWR-INSTALL> ATION

## Page 6: Установка расширения pgpro_pwr {#source-page-006}

Создадим тестовую базу данных на основе demo:
```sh
student$ psql
```
```sql
=> CREATE DATABASE pgpro_pwr TEMPLATE demo;
```
```sql
CREATE DATABASE
```
Для удобства настроим путь поиска:
```sql
=> ALTER DATABASE pgpro_pwr SET search_path TO bookings, public;
```
```sql
ALTER DATABASE
```
Пакет расширения pgpro\_pwr уже установлен в виртуальной машине.
Добавим загрузку библиотек вспомогательных расширений и зададим параметры сбора статистики.
```sql
=> ALTER SYSTEM SET shared_preload_libraries = pg_wait_sampling, pgpro_stats;
```
```sql
ALTER SYSTEM
```
```sql
=> ALTER SYSTEM SET track_io_timing = 'on';
```
```sql
ALTER SYSTEM
```
```sql
=> ALTER SYSTEM SET track_functions = 'all';
```
```sql
ALTER SYSTEM
```
Перезагрузим сервер.
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
```sh
student$ psql -p 5432 -d pgpro_pwr
```
Создадим схему для объектов расширения и добавим расширение в базу данных.
```sql
=> CREATE SCHEMA profile;
```
```sql
CREATE SCHEMA
```
```sql
=> CREATE EXTENSION pgpro_stats;
```
```sql
CREATE EXTENSION
```
```sql
=> CREATE EXTENSION pgpro_pwr SCHEMA profile CASCADE;
```
```sql
NOTICE:  installing required extension "dblink"
CREATE EXTENSION
```
```sql
=> CREATE EXTENSION pg_wait_sampling;
```
```sql
CREATE EXTENSION
```
```text
=> \dx
```
```sql
                                      List of installed extensions
       Name       | Version |   Schema   |                         Description
------------------+---------+------------+------------------------------------------------
--------------
 dblink           | 1.2     | profile    | connect to other PostgreSQL databases from
within a database
 pg_wait_sampling | 1.1     | bookings   | sampling based statistics of wait events
 pgpro_pwr        | 4.13    | profile    | PostgreSQL load profile repository and report
builder
 pgpro_stats      | 1.10    | bookings   | track execution statistics of all SQL
statements executed
 plpgsql          | 1.0.1   | pg_catalog | PL/pgSQL procedural language
(5 rows)
```

## Page 7: Выборки {#source-page-007}

![Source slide page 7: Выборки](images/page-007.png){#source-figure-007 caption="Source slide page 7: Выборки"}

**Данные собираются с зарегистрированных серверов**
- Выборка содержит данные с момента предыдущей выборки

### Комментарии преподавателя

Расширение pgpro\_pwr собирает данные с зарегистрированных серверов. По умолчанию создается активное определение сервера с именем local, соответствующее текущему кластеру.

Данные с активных серверов собираются функцией take\_sample; неактивный сервер можно указывать явно. Если имеется несколько серверов, можно получить выборки с их подмножества функцией take\_sample\_subset.

Выборка содержит информацию об изменениях в измеряемых параметрах СУБД, происшедших с момента предыдущей выборки. Аккумулируемые регулярные выборки позволяют строить отчеты о нагрузке базы данных за предыдущее время. Обычно достаточно получать одну-две выборки в час.

При формировании выборки предыдущая статистика сбрасывается функцией pgpro\_stats\_statements\_reset или pg\_stat\_statements\_reset в зависимости от того, какое расширение поставляет данные.

<https://postgrespro.ru/docs/enterprise/16/pgpro-pwr#PGPRO-PWR-MANAGI> NG-SERVERS

<https://postgrespro.ru/docs/enterprise/16/pgpro-pwr#PGPRO-PWR-SAMPL> ES

## Page 8: Политика хранения {#source-page-008}

![Source slide page 8: Политика хранения](images/page-008.png){#source-figure-008 caption="Source slide page 8: Политика хранения"}

**Настройка**
  - pgpro\_pwr.max\_sample\_age = 7
  - срок хранения в днях, глобально
  - set\_server\_max\_sample\_age()
  - для конкретного сервера

### Комментарии преподавателя

Для выборок можно определять политики хранения. Политика задает временнóй интервал, в течении которого выборки сохраняются (окно удержания). Политику можно установить:

● глобально с помощью параметра конфигурации pgpro\_pwr.max\_sample\_age;

● для конкретного сервера с помощью вызова функции set\_server\_max\_sample\_age.

## Page 9: Выборочные линии {#source-page-009}

![Source slide page 9: Выборочные линии](images/page-009.png){#source-figure-009 caption="Source slide page 9: Выборочные линии"}

**Именованная последовательность выборок**
  - можно использовать для построения отчета
  - можно задать срок хранения (имеет приоритет над политикой)

### Комментарии преподавателя

Для построения отчета по нагрузке требуется две выборки; они задают период, за который были собраны данные для отчета.

Другой способ задания периода для отчета состоит в создании выборочной линии. Линия имеет имя и определяется либо начальной и конечной выборками, либо диапазоном времени.

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

Для управления выборочными линиями предназначены функции:

● create\_baseline — создает выборочную линию;

● drop\_baseline — удаляет выборочную линию;

● keep\_baseline — задает срок хранения;

● show\_baselines — выдает информацию об имеющихся выборочных линиях.

<https://postgrespro.ru/docs/enterprise/16/pgpro-pwr#PGPRO-PWR-BASELI> NES

## Page 10: Получение выборки и создание выборочной линии {#source-page-010}

![Source slide page 10: Получение выборки и создание выборочной линии](images/page-010.png){#source-figure-010 caption="Source slide page 10: Получение выборки и создание выборочной линии"}

Откроем второй сеанс.
```sh
student$ psql -p 5432 -d pgpro_pwr
```
Получим первую выборку. Предыдущая статистика сбрасывается.
```sql
=> SELECT * FROM profile.take_sample();
```
```text
 server | result |  elapsed
--------+--------+------------
 local  | OK     | 00:00:02.3
(1 row)
```
Используем пример соединения хешированием из учебного курса QPT.
Во втором сеансе выполним транзакцию, выделив недостаточный объем оперативной памяти; двухпроходное хеш-соединение будет использовать временные файлы:
```text
=> BEGIN;
```
```text
BEGIN
```
```text
=> SET LOCAL work_mem = '12MB';
```
```text
SET
```
```text
=> SET LOCAL hash_mem_multiplier = 1;
```
```text
SET
```
```sql
=> EXPLAIN (analyze, buffers, costs off, timing off, summary off)
SELECT * FROM bookings b
  JOIN tickets t ON b.book_ref = t.book_ref;
```
```sql
                            QUERY PLAN
------------------------------------------------------------------
 Hash Join (actual rows=366733 loops=1)
   Hash Cond: (t.book_ref = b.book_ref)
   Buffers: shared read=7888, temp read=3491 written=3491
   I/O Timings: shared read=39.412, temp read=10.989 write=38.067
   ->  Seq Scan on tickets t (actual rows=366733 loops=1)
         Buffers: shared read=6176
         I/O Timings: shared read=19.168
   ->  Hash (actual rows=262788 loops=1)
         Buckets: 262144  Batches: 2  Memory Usage: 9071kB
         Buffers: shared read=1712, temp written=690
         I/O Timings: shared read=20.244, temp write=9.460
         ->  Seq Scan on bookings b (actual rows=262788 loops=1)
               Buffers: shared read=1712
               I/O Timings: shared read=20.244
 Planning:
   Buffers: shared hit=208 read=12 dirtied=1
   I/O Timings: shared read=0.269
(17 rows)
```
```text
=> COMMIT;
```
```text
COMMIT
```
Получим вторую выборку — в нее попадут данные о нагрузке после первой выборки:
```sql
=> SELECT * FROM profile.take_sample();
```
```text
 server | result |   elapsed
--------+--------+-------------
 local  | OK     | 00:00:00.79
(1 row)
```
Теперь во втором сеансе выполним транзакцию, выделив достаточно рабочей памяти для хеш-соединения:
```text
=> BEGIN;
```
```text
BEGIN
```
```text
=> SET LOCAL work_mem = '48MB';
```

## Page 11: Page 11 {#source-page-011}

```text
SET
```
```text
=> SET LOCAL hash_mem_multiplier = 3;
```
```text
SET
```
```sql
=> EXPLAIN (analyze, buffers, costs off, timing off, summary off)
SELECT * FROM bookings b
  JOIN tickets t ON b.book_ref = t.book_ref;
```
```sql
                           QUERY PLAN
-----------------------------------------------------------------
 Hash Join (actual rows=366733 loops=1)
   Hash Cond: (t.book_ref = b.book_ref)
   Buffers: shared hit=1744 read=6144
   I/O Timings: shared read=21.886
   ->  Seq Scan on tickets t (actual rows=366733 loops=1)
         Buffers: shared hit=32 read=6144
         I/O Timings: shared read=21.886
   ->  Hash (actual rows=262788 loops=1)
         Buckets: 524288  Batches: 1  Memory Usage: 18190kB
         Buffers: shared hit=1712
         ->  Seq Scan on bookings b (actual rows=262788 loops=1)
               Buffers: shared hit=1712
 Planning:
   Buffers: shared hit=8
(14 rows)
```
```text
=> COMMIT;
```
```text
COMMIT
```
А сейчас получим третью выборку — в нее попадут данные о нагрузке после второй выборки:
```sql
=> SELECT * FROM profile.take_sample();
```
```text
 server | result |   elapsed
--------+--------+-------------
 local  | OK     | 00:00:00.66
(1 row)
```
Список выборок:
```sql
=> SELECT * FROM profile.show_samples();
```
```text
 sample |      sample_time       | sizes_collected | dbstats_reset | clustats_reset |
archstats_reset
--------+------------------------+-----------------+---------------+----------------+-----
------------
      1 | 2026-07-27 23:42:53+03 | f               |               |                |
      2 | 2026-07-27 23:42:57+03 | f               |               |                |
      3 | 2026-07-27 23:43:00+03 | f               |               |                |
(3 rows)
```
Сформируем из имеющихся выборок две выборочные линии.
```sql
=> SELECT profile.create_baseline(baseline=>'BaseLine1', start_id=>1, end_id=>2);
```
```text
 create_baseline
-----------------
               1
(1 row)
```
```sql
=> SELECT profile.create_baseline(baseline=>'BaseLine2', start_id=>2, end_id=>3);
```
```text
 create_baseline
-----------------
               2
(1 row)
```
Список выборочных линий:
```sql
=> SELECT * FROM profile.show_baselines();
```

## Page 12: Page 12 {#source-page-012}

```text
 baseline  | min_sample | max_sample | keep_until_time
-----------+------------+------------+-----------------
 BaseLine1 |          1 |          2 |
 BaseLine2 |          2 |          3 |
(2 rows)
```

## Page 13: Размеры отношений {#source-page-013}

![Source slide page 13: Размеры отношений](images/page-013.png){#source-figure-013 caption="Source slide page 13: Размеры отношений"}

**Политика анализа размеров**
  - разрешенное окно в течение суток для сбора данных о размерах
  - минимальный промежуток между выборками, содержащими размеры

### Комментарии преподавателя

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

Однако чаще всего достаточно собирать информацию о размерах один раз в сутки. Для этого можно определить политику анализа размеров для серверов, которая устанавливает:

● окно в течение суток, когда разрешается сбор сведений о размерах отношений;

● минимальный промежуток между двумя выборками со сведениями о размерах.

Политику можно задать с помощью функции set\_server\_size\_sampling.

Просмотреть политики для серверов можно, вызвав функцию show\_servers\_size\_sampling.

<https://postgrespro.ru/docs/enterprise/16/pgpro-pwr#PGPRO-PWR-RELATI> ON-SIZES-COLLECTION

## Page 14: Отчеты {#source-page-014}

**Отчеты pgpro\\\_pwr формируются в формате HTML**
  - get\_report() — обычные отчеты, предоставляющие статистику
  - по нагрузке для заданного интервала
  - get\_diffreport() — разностные отчеты со статистикой
  - по одинаковым объектам в двух сравниваемых интервалах
- Выбранный элемент отчета автоматически выделяется в других разделах отчета
- Настройка
  - pgpro\_pwr.max = 7
  - число первых по некоторому критерию
  - объектов, выбираемых для каждой
  - таблицы отчета

### Комментарии преподавателя

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

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

Разделы отчета подробно описаны в документации: <https://postgrespro.ru/docs/enterprise/16/pgpro-pwr#PGPRO-PWR-REPOR> T-GENERATION

## Page 15: Отчеты {#source-page-015}

Получим отчет. Для построения обычного отчета достаточно указать две выборки или одну выборочную линию.
В плане запроса, выполненного в условиях недостатка рабочей памяти, видно, что используются временные файлы для двухпроходного хеш-соединения.
Раздел отчета "Top SQL by temp usage" должен содержать сведения об этом запросе.
```sh
student$ psql -d pgpro_pwr -Aqtc 'SELECT profile.get_report(1,2)' -o /tmp/report_1_2.html
```
Открываем /tmp/report\_1\_2.html...
```sh
student$ open /tmp/report_1_2.html
```
Получим разностный отчет. Используем две выборочные линии.
В разностном отчете должно быть заметно, что во втором запросе рабочей памяти хватило для выполнения однопроходного хеш-соединения и временные файлы не использовались.
В отчете просмотрите разделы:
Top SQL by temp usage; Load distribution among heavily loaded databases; Load distribution.
```sh
student$ psql -d pgpro_pwr -Aqtc "SELECT profile.get_diffreport('BaseLine1','BaseLine2')" -o
/tmp/report_diff.html
```
Открываем /tmp/report\_diff.html...
```sh
student$ open /tmp/report_diff.html
```

## Page 16: Итоги {#source-page-016}

**Расширение pgpro\\\_pwr предназначено для выявления ресурсоемких операций в БД**
- Статистика собирается расширениями pgpro\_stats или pg\_stat\_statements
- Поддерживается политика хранения выборок
- Можно получать обычные и разностные отчеты в HTML

## Page 17: Практика {#source-page-017}

1. Подготовьте СУБД для работы с расширением pgpro\_pwr. 2. Создайте базу данных и установите расширение pgpro\_pwr. 3. Проведите нагрузочное тестирование с помощью pgbench, получив две выборки — до и после тестирования. 4. Создайте новое табличное пространство и сделайте выборку. 5. Снова проведите тестирование с помощью pgbench так, чтобы индексы были в новом табличном пространстве, после чего сделайте еще одну выборку. 6. Получите разностный отчет для первого и второго тестов.

### Комментарии преподавателя

1. Подключите разделяемые библиотеки pg\_wait\_sampling и pgpro\_stats.

2. В базе данных создайте схему для объектов расширения pgpro\_pwr.

3. Выполните обычную инициализацию таблиц pgbench и обычный тест нагрузки, например, на 60 секунд.

4. Предварительно создайте каталог для табличного пространства, например, в домашнем каталоге пользователя postgres.

5. Заново проведите инициализацию таблиц pgbench, указав для табличного пространства ключ --index-tablespace. Сделайте новую выборку.

6. Получите разностный отчет с двумя промежутками.

## Page 18: 1. Подготовка СУБД для работы с расширением pgpro_pwr {#source-page-018}

```sh
student$ psql
```
Подключим разделяемые библиотеки.
Расширение pgpro\_pwr получает сводную статистику ожиданий от расширения pg\_wait\_sampling:
```sql
=> ALTER SYSTEM SET shared_preload_libraries = pg_wait_sampling, pgpro_stats;
```
```sql
ALTER SYSTEM
```
Параметр track\_io\_timing нужен для анализа времени, затраченного операторами на чтение или запись блоков:
```sql
=> ALTER SYSTEM SET track_io_timing = 'on';
```
```sql
ALTER SYSTEM
```
Параметр track\_functions позволяет отслеживать вызовы пользовательских функций:
```sql
=> ALTER SYSTEM SET track_functions = 'all';
```
```sql
ALTER SYSTEM
```
Перезагрузим сервер.
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```
### 2. Создание базы данных и установка расширения pgpro\\\_pwr
```sh
student$ psql
```
Создадим базу данных.
```sql
=> CREATE DATABASE pgpro_pwr;
```
```sql
CREATE DATABASE
```
```sql
=> \c pgpro_pwr
```
```text
You are now connected to database "pgpro_pwr" as user "student".
```
Создадим схему для хранения объектов расширения и установим расширение.
```sql
=> CREATE SCHEMA profile;
```
```sql
CREATE SCHEMA
```
```sql
=> CREATE EXTENSION pgpro_pwr SCHEMA profile CASCADE;
```
```sql
NOTICE:  installing required extension "dblink"
CREATE EXTENSION
```
```sql
=> CREATE EXTENSION pg_wait_sampling;
```
```sql
CREATE EXTENSION
```
```sql
=> CREATE EXTENSION pgpro_stats;
```
```sql
CREATE EXTENSION
```
```text
=> \dx
```
```sql
                                      List of installed extensions
       Name       | Version |   Schema   |                         Description
------------------+---------+------------+------------------------------------------------
--------------
 dblink           | 1.2     | profile    | connect to other PostgreSQL databases from
within a database
 pg_wait_sampling | 1.1     | public     | sampling based statistics of wait events
 pgpro_pwr        | 4.13    | profile    | PostgreSQL load profile repository and report
builder
 pgpro_stats      | 1.10    | public     | track execution statistics of all SQL
statements executed
 plpgsql          | 1.0.1   | pg_catalog | PL/pgSQL procedural language
(5 rows)
```

## Page 19: 3. Нагрузочное тестирование {#source-page-019}

Сделаем выборку:
```sql
=> SELECT * FROM profile.take_sample();
```
```text
 server | result |   elapsed
--------+--------+-------------
 local  | OK     | 00:00:02.64
(1 row)
```
Инициализируем нагрузочные таблицы pgbench:
```sh
student$ /opt/pgpro/ent-16/bin/pgbench -i pgpro_pwr
```
```sql
dropping old tables...
NOTICE:  table "pgbench_accounts" does not exist, skipping
NOTICE:  table "pgbench_branches" does not exist, skipping
NOTICE:  table "pgbench_history" does not exist, skipping
NOTICE:  table "pgbench_tellers" does not exist, skipping
creating tables...
generating data (client-side)...
100000 of 100000 tuples (100%) done (elapsed 0.17 s, remaining 0.00 s)
vacuuming...
creating primary keys...
done in 0.76 s (drop tables 0.00 s, create tables 0.10 s, client-side generate 0.35 s,
vacuum 0.12 s, primary keys 0.19 s).
```
Запустим pgbench на 30 секунд:
```sh
student$ /opt/pgpro/ent-16/bin/pgbench -T30 pgpro_pwr
```
```sql
pgbench (16.14)
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 1
number of threads: 1
maximum number of tries: 1
duration: 30 s
number of transactions actually processed: 3258
number of failed transactions: 0 (0.000%)
latency average = 9.208 ms
initial connection time = 3.571 ms
tps = 108.595587 (without initial connection time)
```
Получим вторую выборку, в которую попадут данные о нагрузке при инициализации и нагрузочном тесте:
```sql
=> SELECT * FROM profile.take_sample();
```
```text
 server | result |  elapsed
--------+--------+------------
 local  | OK     | 00:00:00.9
(1 row)
```
### 4. Создание нового табличного пространства
Создадим табличное пространство.
```sh
postgres$ mkdir /var/lib/postgresql/ts_dir
```
```sql
=> CREATE TABLESPACE ts_idx LOCATION '/var/lib/postgresql/ts_dir';
```
```sql
CREATE TABLESPACE
```
Сделаем выборку:
```sql
=> SELECT * FROM profile.take_sample();
```
```text
 server | result |   elapsed
--------+--------+-------------
 local  | OK     | 00:00:00.75
(1 row)
```
### 5. Нагрузочное тестирование при размещении индексов в отдельном табличном пространстве

## Page 20: Page 20 {#source-page-020}

Инициализируем нагрузочные таблицы pgbench:
```sh
student$ /opt/pgpro/ent-16/bin/pgbench -i --index-tablespace=ts_idx pgpro_pwr
```
```sql
dropping old tables...
creating tables...
generating data (client-side)...
100000 of 100000 tuples (100%) done (elapsed 0.11 s, remaining 0.00 s)
vacuuming...
creating primary keys...
done in 0.63 s (drop tables 0.02 s, create tables 0.03 s, client-side generate 0.30 s,
vacuum 0.11 s, primary keys 0.15 s).
```
Запустим pgbench на 30 секунд:
```sh
student$ /opt/pgpro/ent-16/bin/pgbench -T30 pgpro_pwr
```
```sql
pgbench (16.14)
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 1
number of threads: 1
maximum number of tries: 1
duration: 30 s
number of transactions actually processed: 3280
number of failed transactions: 0 (0.000%)
latency average = 9.146 ms
initial connection time = 5.295 ms
tps = 109.340623 (without initial connection time)
```
Получим еще одну выборку:
```sql
=> SELECT * FROM profile.take_sample();
```
```text
 server | result |   elapsed
--------+--------+-------------
 local  | OK     | 00:00:00.74
(1 row)
```
Получим список выборок:
```sql
=> SELECT * FROM profile.show_samples();
```
```text
 sample |      sample_time       | sizes_collected | dbstats_reset | clustats_reset |
archstats_reset
--------+------------------------+-----------------+---------------+----------------+-----
------------
      1 | 2026-07-28 00:14:18+03 | f               |               |                |
      2 | 2026-07-28 00:14:52+03 | f               |               |                |
      3 | 2026-07-28 00:14:53+03 | f               |               |                |
      4 | 2026-07-28 00:15:25+03 | f               |               |                |
(4 rows)
```
### 5. Получение разностного отчета
Получим разностный отчет.
```sh
student$ psql -d pgpro_pwr -Aqtc "SELECT profile.get_diffreport(1,2,3,4)" -o /tmp/report_diff.html
```
Открываем /tmp/report\_diff.html...
```sh
student$ open /tmp/report_diff.html
```
### Уборка
Удалим созданную базу данных, табличное пространство и файл отчета.
```sql
=> \c student
```
```text
You are now connected to database "student" as user "student".
```
```sql
=> DROP DATABASE pgpro_pwr WITH (FORCE);
```
```sql
DROP DATABASE
```
```sql
=> DROP TABLESPACE ts_idx;
```
```sql
DROP TABLESPACE
```

## Page 21: Page 21 {#source-page-021}

```sh
student$ sudo rm -rf /var/lib/postgresql/ts_dir
```
```sh
student$ sudo rm -f /tmp/report_diff.html
```
Сбросим настройки параметров конфигурации.
```sql
=> ALTER SYSTEM RESET ALL;
```
```sql
ALTER SYSTEM
```
```sh
student$ sudo systemctl restart postgrespro-ent-16.service
```

## Page 22: Практика PPEM {#source-page-022}

1. В основном экземпляре создайте базу данных demo\_pwr из шаблона demo. Подготовьте новую базу к работе с pgpro\_pwr. 2. Сделайте снимок статистики новой базы с учетом размеров отношений. 3. Удалите схему bookings из базы данных demo\_pwr. 4. Снова сделайте снимок статистики, подобный снимку из п. 2. 5. Постройте отчет по снимкам, построенным в пунктах 2 и 4, и найдите в нем данные, отражающие изменения, сделанные в п. 3.

### Комментарии преподавателя

1. В созданной базе установите необходимые расширения (нужные библиотеки уже были загружены в основном практическом задании) и создайте сервер профилировщика.

## Page 23: 1. Создание базы и подготовка к работе с pgpro_pwr {#source-page-023}

На вкладке «Базы данных» нажмите «Создать базу данных» и заполните форму, указав базу demo в качестве шаблона. Выбрав новую базу, из вкладки «Расширения» создайте в ней расширение pgpro\_pwr, включая установку зависимых расширений. Используя вкладку «Профилировщик» / «Серверы», создайте сервер профилировщика для новой базы — в строке подключения укажите dbname=demo\_pwr.
### 2. Снимок статистики
Выберите вкладку «Снимки статистики» и нажмите «Сделать снимок» с выключенным параметром skip\_sizes.
### 3. Изменения в данных
На вкладке «Базы данных» выберите demo\_pwr, а в ней схему bookings. В столбце «Действия» для указанной схемы нажмите на пиктограмму «Удалить». Подтвердите удаление схемы, включив параметр каскадного удаления.
### 4. Повторный снимок статистики
Сделайте еще один снимок статистики, как в п. 2
### 5. Построение и просмотр отчета
На вкладке «Профилировщик» / «Построение отчетов» создайте стандартный отчет по снимкам, созданным в пунктах 2 и 4. В полученном отчете, в разделе «Server statistics» / «Database statistics», крайний правый столбец будет отражать изменение объема данных.
