Статьи

Настройка PostgreSQL с помощью pgbench

Когда дело доходит до настройки производительности среды, часто первое, с чего начать, — это база данных. Причина этого в том, что большинство приложений очень сильно зависят от какой-либо базы данных.

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

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

PostgreSQL — это очень популярная реляционная база данных с открытым исходным кодом. Одна из приятных особенностей PostgreSQL заключается в том, что было создано немало инструментов, помогающих управлять PostgreSQL; pgbench — один из таких инструментов.

Исследуя pgbench , мы также будем использовать его для измерения прироста / потери производительности для обычной настраиваемой версии PostgreSQL.

Настройка экземпляра PostgreSQL

Прежде чем мы сможем использовать pgbench для настройки службы базы данных, мы должны сначала запустить эту службу базы данных. Ниже приведены шаги по настройке базового экземпляра PostgreSQL на сервере Ubuntu 16.04 .

Установка с помощью apt-get

Установить PostgreSQL в системе Ubuntu довольно просто. Большая часть работы выполняется простым запуском команды apt-get .

1
# apt-get install postgresql postgresql-contrib

Приведенная выше команда apt-get устанавливает оба пакета postgresql и postgresql-contrib . Пакет postgresql устанавливает базовый сервис PostgreSQL.

Пакет postgresql-contrib устанавливает дополнительные материалы для PostgreSQL. Эти материалы еще не были добавлены в официальный пакет, но часто предоставляют довольно мало функциональности.

С установленными пакетами у нас теперь есть работающий экземпляр PostgreSQL. Мы можем проверить это с помощью команды systemctl чтобы проверить состояние PostgreSQL.

1
2
3
4
5
6
7
8
9
# systemctl status postgresql
● postgresql.service - PostgreSQL RDBMS
   Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled)
   Active: active (exited) since Mon 2017-01-02 21:14:36 UTC; 7h ago
  Process: 16075 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
 Main PID: 16075 (code=exited, status=0/SUCCESS)
 
Jan 02 21:14:36 ubuntu-xenial systemd[1]: Starting PostgreSQL RDBMS...
Jan 02 21:14:36 ubuntu-xenial systemd[1]: Started PostgreSQL RDBMS.

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

Создание базы данных

Когда мы установили пакет postgresql , этот пакет включал создание пользователя с именем postgres . Этот пользователь используется как владелец запущенного экземпляра. Он также служит администратором для службы PostgreSQL.

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

1
# su - postgres

После переключения на пользователя postgres мы можем войти в работающий экземпляр с помощью клиента PostgreSQL, psql .

1
2
3
4
5
$ psql
psql (9.5.5)
Type "help" for help.
 
postgres=#

После выполнения команды psql мы оказались в среде командной строки PostgreSQL. Отсюда мы можем выдавать операторы SQL или использовать специальные клиентские команды для выполнения действий.

Например, мы можем вывести список текущих баз данных, выполнив команду \list .

01
02
03
04
05
06
07
08
09
10
postgres-# \list
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges  
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(3 rows)

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

Для нашего сегодняшнего тестирования мы будем создавать новую базу данных. Давайте продолжим и создадим эту базу данных, назвав ее примером . Мы можем сделать это, выполнив следующую инструкцию SQL:

1
CREATE DATABASE example;

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

01
02
03
04
05
06
07
08
09
10
11
postgres=# \list
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges  
-----------+----------+----------+-------------+-------------+-----------------------
 example   | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(4 rows)

На данный момент у нас есть пустая база данных с именем example . С этого момента нам нужно вернуться в нашу оболочку bash для выполнения команд pgbench . Мы можем сделать это, введя команду \q (quit).

1
postgres-# \q

Выйдя из среды командной строки PostgreSQL, мы можем начать использовать pgbench для оценки производительности нашего экземпляра базы данных.

Использование pgbench для измерения производительности

Одной из самых сложных вещей в измерении производительности базы данных является генерирование достаточной нагрузки. Популярный вариант — просто бомбардировать тестовые экземпляры целевого приложения или приложений тестовыми транзакциями. Хотя это полезный тест, который обеспечивает производительность БД по отношению к приложению, иногда он может быть проблематичным, поскольку узкие места приложения могут ограничивать тестирование базы данных.

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

В этой статье мы будем использовать пример базы данных, которая поставляется с pgbench .

Настройка примера базы данных pgbench

Настройка примера базы данных довольно проста и довольно быстра. Мы можем запустить этот процесс, выполнив pgbench с опцией -i (initialize).

1
2
3
4
5
6
$ pgbench -i -s 50 example
creating tables...
5000000 of 5000000 tuples (100%) done (elapsed 5.33 s, remaining 0.00 s)
vacuum...
set primary keys...
done.

В приведенной выше команде мы выполнили pgbench с параметром -i и параметром -s за которым следует имя базы данных ( example ).

Опция -i (initialize) скажет pgbench инициализировать указанную базу данных. Это означает, что pgbench создаст следующие таблицы в базе данных example .

1
2
3
4
5
6
table                   # of rows
---------------------------------
pgbench_branches        1
pgbench_tellers         10
pgbench_accounts        100000
pgbench_history         0

По умолчанию pgbench создаст таблицы выше с количеством строк, показанных выше. Это создает простую базу данных 16MB .

Поскольку мы будем использовать pgbench для измерения изменений в производительности, небольшой базы данных размером 16MB будет недостаточно, чтобы подчеркнуть нашу ситуацию. Здесь вступает в игру опция -s (масштабирование).

Опция -s используется для умножения количества строк, введенных в каждую таблицу. В приведенной выше команде мы ввели опцию «масштабирования», равную 50 . Это сказало pgbench создать базу данных в 50 раз больше размера по умолчанию.

Это означает, что наша таблица pgbench_accounts теперь содержит 5,000,000 записей. Это также означает, что размер нашей базы данных теперь составляет 800MB 50 x 16MB ( 50 x 16MB ).

Чтобы убедиться, что наши таблицы были созданы успешно, давайте продолжим и снова запустим клиент psql .

1
2
3
4
5
$ psql -d example
psql (9.5.5)
Type "help" for help.
 
example=#

В приведенной выше команде мы использовали флаг -d (база данных), чтобы сообщить psql не только о подключении к службе PostgreSQL, но и о переключении на пример базы данных.

Поскольку в настоящее время мы используем пример базы данных, мы можем выполнить команду \dt для просмотра списка таблиц, доступных в этой базе данных.

1
2
3
4
5
6
7
8
9
example=# \dt
              List of relations
 Schema |       Name       | Type  |  Owner  
--------+------------------+-------+----------
 public | pgbench_accounts | table | postgres
 public | pgbench_branches | table | postgres
 public | pgbench_history  | table | postgres
 public | pgbench_tellers  | table | postgres
(4 rows)

Из таблицы выше видно, что pgbench создал четыре ожидаемые таблицы. Это означает, что наша база данных заполнена и готова к использованию для измерения производительности нашего экземпляра базы данных.

Установление базовой линии

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

Давайте продолжим и вызовем pgbench чтобы установить базовый уровень для нашего «готового» экземпляра PostgreSQL.

01
02
03
04
05
06
07
08
09
10
11
12
$ pgbench -c 10 -j 2 -t 10000 example
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 50
query mode: simple
number of clients: 10
number of threads: 2
number of transactions per client: 10000
number of transactions actually processed: 100000/100000
latency average: 4.176 ms
tps = 2394.718707 (including connections establishing)
tps = 2394.874350 (excluding connections establishing)

При вызове pgbench мы добавляем в команду довольно много опций. Первым является -c (клиенты), который используется для определения количества клиентов, с которыми нужно соединиться. Для этого тестирования я использовал 10 чтобы указать pgbench выполнить с 10 клиентами.

Это означает, что когда pgbench выполняет тесты, он открывает 10 разных сессий.

Следующая опция — флаг -j (threads). Этот флаг используется для определения количества рабочих процессов для pgbench . В приведенной выше команде я указал значение 2 . Это скажет pgbench запустить два рабочих процесса во время бенчмаркинга.

Третий параметр — -t (транзакции), который используется для указания количества транзакций, которые нужно выполнить. В приведенной выше команде я указал значение 10,000 . Однако это не означает, что с нашей службой базы данных будет выполнено только 10,000 транзакций. Это означает, что каждый клиентский сеанс будет выполнять 10,000 транзакций.

Подводя итог, можно сказать, что базовый тестовый запуск состоял из двух рабочих процессов pgbench имитирующих 10,000 транзакций от 10 клиентов, в общей сложности 100,000 транзакций.

С этим пониманием давайте посмотрим на результаты этого первого теста.

01
02
03
04
05
06
07
08
09
10
11
12
$ pgbench -c 10 -j 2 -t 10000 example
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 50
query mode: simple
number of clients: 10
number of threads: 2
number of transactions per client: 10000
number of transactions actually processed: 100000/100000
latency average: 4.176 ms
tps = 2394.718707 (including connections establishing)
tps = 2394.874350 (excluding connections establishing)

Вывод pgbench содержит довольно мало информации. Большинство из них описывает выполняемые тестовые сценарии. Больше всего нас интересует следующее:

1
2
tps = 2394.718707 (including connections establishing)
tps = 2394.874350 (excluding connections establishing)

Исходя из этих результатов, наша базовая линия составляет 2,394 транзакции базы данных в секунду. Давайте продолжим и посмотрим, сможем ли мы увеличить это число, изменив простой параметр конфигурации в PostgreSQL.

Добавляем больше кеша

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

Чтобы показать, как мы можем использовать pgbench для настройки производительности, мы будем корректировать это значение для тестирования прироста / снижения производительности.

По умолчанию значение shared_buffers установлено в 128MB , что является довольно низким значением, учитывая объем доступной памяти на большинстве серверов сегодня. Мы можем убедиться в этом сами, посмотрев содержимое файла /etc/postgresql/9.5/main/postgresql.conf . В этом файле мы должны увидеть следующее.

1
2
3
4
# - Memory -
 
shared_buffers = 128MB                  # min 128kB
                                        # (change requires restart)

Давайте продолжим и переключим это значение на 256MB , фактически удвоив доступное пространство кеша.

1
2
3
4
# - Memory -
 
shared_buffers = 256MB                  # min 128kB
                                        # (change requires restart)

После завершения нам нужно будет перезапустить сервис PostgreSQL. Мы можем сделать это, выполнив команду systemctl с параметром restart .

1
# systemctl restart postgresql

Как только сервис будет полностью запущен, мы можем снова использовать pgbench для измерения нашей производительности.

01
02
03
04
05
06
07
08
09
10
11
12
$ pgbench -c 10 -j 2 -t 10000 example
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 50
query mode: simple
number of clients: 10
number of threads: 2
number of transactions per client: 10000
number of transactions actually processed: 100000/100000
latency average: 3.921 ms
tps = 2550.313477 (including connections establishing)
tps = 2550.480149 (excluding connections establishing)

В нашем предыдущем базовом тесте мы смогли достичь скорости 2,394 транзакций в секунду. В этом последнем запуске после обновления параметра shared_buffers мы смогли выполнить 2,550 транзакций в секунду, увеличившись на 156 . Хотя это неплохое начало, мы все равно можем пойти дальше.

Хотя параметр shared_buffers может начинаться с 128MB , рекомендуемое значение этого параметра — одна четвертая системной памяти. Наша тестовая система имеет 2GB системной памяти, значение, которое мы можем проверить с помощью команды free .

1
2
3
4
$ free -m
              total        used        free      shared  buff/cache   available
Mem:           2000          54         109         548        1836        1223
Swap:             0           0           0

В приведенном выше выводе мы видим, что в столбце 2000MB в строке для памяти 2000MB значение 2000MB . В этом столбце отображается общий объем физической памяти, доступной для системы. Мы также можем видеть в available столбце, что 1223MB показывает доступные. Это означает, что у нас есть до 1.2 ГБ свободной памяти, которую мы можем использовать в наших настройках.

Если мы изменим наш параметр shared_buffers на рекомендуемое значение одной четвертой системной памяти, нам потребуется изменить его на 512MB . Давайте сделаем это изменение и повторно pgbench наш тест pgbench .

1
2
3
4
# - Memory -
 
shared_buffers = 512MB                  # min 128kB
                                        # (change requires restart)

shared_buffers значение shared_buffers в /etc/postgresql/9.5/main/postgresql.conf , мы можем продолжить и перезапустить службу PostgreSQL.

1
# systemctl restart postgresql

После перезапуска перезапустим наш тест.

01
02
03
04
05
06
07
08
09
10
11
12
$ pgbench -c 10 -j 2 -t 10000 example
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 50
query mode: simple
number of clients: 10
number of threads: 2
number of transactions per client: 10000
number of transactions actually processed: 100000/100000
latency average: 3.756 ms
tps = 2662.750932 (including connections establishing)
tps = 2663.066421 (excluding connections establishing)

На этот раз нашей системе удалось достичь 2,662 транзакций в секунду, что дополнительно увеличило 112 транзакций в секунду. Поскольку количество транзакций в секунду увеличилось как минимум в 100 раз, давайте сделаем еще один шаг и посмотрим, что произойдет, если изменить это значение на 1GB .

1
2
3
4
# - Memory -
 
shared_buffers = 1024MB                 # min 128kB
                                        # (change requires restart)

После обновления значения нам нужно будет еще раз перезапустить сервис PostgreSQL.

1
# systemctl restart postgresql

После перезапуска службы мы можем перезапустить наш тест.

01
02
03
04
05
06
07
08
09
10
11
12
$ pgbench -c 10 -j 2 -t 10000 example
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 50
query mode: simple
number of clients: 10
number of threads: 2
number of transactions per client: 10000
number of transactions actually processed: 100000/100000
latency average: 3.744 ms
tps = 2670.791865 (including connections establishing)
tps = 2671.079076 (excluding connections establishing)

На этот раз количество транзакций в секунду увеличилось с 2,662 до 2,671 и число операций выросло на 9 в секунду. Это ситуация, когда мы получаем убывающую отдачу.

Хотя во многих средах возможно увеличить значение shared_buffers за пределы одной четвертой рекомендации, это не возвращает те же результаты для этой тестовой базы данных.

Резюме

Исходя из результатов нашего тестирования, мы видим, что изменение значения shared_buffers со 128MB до 512MB в нашей тестовой системе привело к увеличению производительности на 268 транзакций в секунду. Исходя из наших базовых результатов, это увеличение производительности на 10 процентов .

Мы сделали все это на базовом экземпляре PostgreSQL, используя образец базы данных pgbench . Это значит, что нам не нужно было загружать наше приложение, чтобы получить базовый показатель эффективности работы PostgreSQL.

Хотя мы смогли увеличить нашу пропускную способность, изменив параметр shared_buffers в PostgreSQL, доступно гораздо больше параметров настройки. Для тех, кто хочет настроить экземпляр PostgreSQL, я настоятельно рекомендую проверить вики PostgreSQL.

Ссылка: Настройка PostgreSQL с pgbench от нашего партнера по JCG Бена Кейна в блоге Codeship Blog .