Управляемые пулы соединений с базами данных и сравнительный анализ PostgreSQL с помощью pgbench

Вступление

Управляемые базы данных DigitalOcean позволяют масштабировать базу данных PostgreSQL несколькими способами. Одним из таких методов является встроенный диспетчер подключений, который позволяет эффективно обрабатывать большое количество клиентских подключений и уменьшить нагрузку на ЦП и память этих открытых подключений. Используя пул соединений и разделяя фиксированный набор перерабатываемых соединений, вы можете обрабатывать значительно больше одновременных клиентских соединений и извлекать дополнительную производительность из вашей базы данных PostgreSQL.

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

Предпосылки

Для завершения этого урока вам понадобится:

  • Кластер управляемой базой данных PostgreSQL DigitalOcean. Чтобы узнать, как подготовить и настроить кластер DigitalOcean PostgreSQL, обратитесь к документации по управляемой базе данных product.

  • Клиентский компьютер с установленным PostgreSQL. По умолчанию ваша установка PostgreSQL будет содержать утилиту для тестирования производительности + pgbench + и клиент + psql +, которые мы будем использовать в этом руководстве. Обратитесь к Как установить и использовать PostgreSQL на Ubuntu 18.04, чтобы узнать, как установить PostgreSQL. Если вы не запускаете Ubuntu на своем клиентском компьютере, вы можете использовать средство поиска версий, чтобы найти соответствующее руководство.

После того, как у вас есть кластер DigitalOcean PostgreSQL и запущен клиентский компьютер с установленным + pgbench +, вы готовы начать с этого руководства.

Шаг 1 - Создание и инициализация + benchmark + Database

Прежде чем мы создадим пул соединений для нашей базы данных, мы сначала создадим базу данных + benchmark + в нашем кластере PostgreSQL и наполним ее некоторыми фиктивными данными, для которых + pgbench + будет выполнять свои тесты. Утилита + pgbench + многократно запускает серию из пяти команд SQL (состоящих из + SELECT +, + UPDATE + и + INSERT +) в транзакции, используя несколько потоков и клиентов, и вычисляет полезный показатель производительности называется T транзакций р эр с сек (TPS). TPS - это показатель пропускной способности базы данных, который подсчитывает количество атомарных транзакций, обработанных базой данных за одну секунду Чтобы узнать больше о конкретных командах, выполняемых + pgbench +, обратитесь к What is «Транзакция», фактически выполняемая в pgbench? из официальной документации + pgbench +.

Давайте начнем с подключения к нашему кластеру PostgreSQL и создания базы данных + benchmark +.

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

изображение: https: //assets.digitalocean.com/articles/managed_db_pools/conn_details.png [Подробности подключения к кластеру PostgreSQL]

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

  • Администратор: + doadmin +

  • Пароль администратора:

  • Конечная точка кластера: + dbaas-test-do-user-3587522-0.db.on digitalocean.com

  • Порт подключения: + 25060 +

  • База данных для подключения: + defaultdb +

  • Режим SSL: + require + (используйте соединение с шифрованием SSL для повышения безопасности)

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

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

Подключитесь к вашему кластеру, используя + psql + и только что скопированную строку подключения:

psql postgresql://doadmin:@:25060/defaultdb?sslmode=require

Вы должны увидеть следующее приглашение клиента PostgreSQL, указывающее, что вы успешно подключились к кластеру PostgreSQL:

Outputpsql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1))
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

defaultdb=>

Отсюда создайте базу данных + benchmark +:

CREATE DATABASE benchmark;

Вы должны увидеть следующий вывод:

OutputCREATE DATABASE

Теперь отключитесь от кластера:

\q

Прежде чем запускать тесты + pgbench +, нам нужно заполнить эту базу данных + benchmark + некоторыми таблицами и фиктивными данными, необходимыми для запуска тестов.

Для этого мы запустим + pgbench + со следующими флагами:

  • + -h +: конечная точка кластера PostgreSQL

  • + -p +: порт подключения кластера PostgreSQL

  • + -U +: имя пользователя базы данных

  • + -i +: указывает, что мы хотели бы инициализировать базу данных + benchmark + с помощью таблиц сравнительного анализа и их фиктивных данных.

  • + -s +: установить масштабный коэффициент 150, который умножит размеры таблицы на 150. Масштабный коэффициент по умолчанию + 1 + приводит к таблицам следующих размеров:

    table                   # of rows
    ---------------------------------
    pgbench_branches        1
    pgbench_tellers         10
    pgbench_accounts        100000
    pgbench_history         0

    + Используя масштабный коэффициент 150, таблица + pgbench_accounts + будет содержать 15 000 000 строк.

Выполните полную команду + pgbench +:

pgbench -h  -p 25060 -U doadmin -i -s 150 benchmark

После выполнения этой команды вам будет предложено ввести пароль для указанного вами пользователя базы данных. Введите пароль и нажмите + ENTER.

Вы должны увидеть следующий вывод:

Outputdropping 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...
100000 of 15000000 tuples (0%) done (elapsed 0.19 s, remaining 27.93 s)
200000 of 15000000 tuples (1%) done (elapsed 0.85 s, remaining 62.62 s)
300000 of 15000000 tuples (2%) done (elapsed 1.21 s, remaining 59.23 s)
400000 of 15000000 tuples (2%) done (elapsed 1.63 s, remaining 59.44 s)
500000 of 15000000 tuples (3%) done (elapsed 2.05 s, remaining 59.51 s)
. . .
14700000 of 15000000 tuples (98%) done (elapsed 70.87 s, remaining 1.45 s)
14800000 of 15000000 tuples (98%) done (elapsed 71.39 s, remaining 0.96 s)
14900000 of 15000000 tuples (99%) done (elapsed 71.91 s, remaining 0.48 s)
15000000 of 15000000 tuples (100%) done (elapsed 72.42 s, remaining 0.00 s)
vacuuming...
creating primary keys...
done.

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

Шаг 2 - Выполнение базового теста + pgbench +

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

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

изображение: https: //assets.digitalocean.com/articles/managed_db_pools/no_connection_pool.png [Соединения с базой данных без объединения]

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

изображение: https: //assets.digitalocean.com/articles/managed_db_pools/with_connection_pool.png [Соединения с базой данных с пулами]

Пул соединений может быть реализован либо на стороне приложения, либо в качестве промежуточного программного обеспечения между базой данных и вашим приложением. Пул соединений с управляемыми базами данных построен поверх pgBouncer, легкого пула соединений с промежуточным ПО с открытым исходным кодом для PostgreSQL. Его интерфейс доступен через пользовательский интерфейс Cloud Control Panel.

Перейдите к * Базы данных * на панели управления, а затем щелкните в своем кластере PostgreSQL. Отсюда, нажмите на * Connection Pools *. Затем нажмите * Создать пул соединений *. Вы должны увидеть следующее окно конфигурации:

изображение: https: //assets.digitalocean.com/articles/managed_db_pools/connection_pool_blank.png [Окно настройки пулов подключений]

Здесь вы можете настроить следующие поля:

  • * Имя пула *: уникальное имя для вашего пула соединений

  • * База данных *: база данных, для которой вы хотите объединить подключения

  • * Пользователь *: пользователь PostgreSQL, для которого пул соединений будет аутентифицироваться как

  • * Mode *: один из * Session *, * Transaction * или * Statement *. Эта опция контролирует, как долго пул назначает клиентскому серверу бэкэнд-соединение.

  • * Session *: клиент удерживает соединение до тех пор, пока оно явно не отключится.

  • * Транзакция *: клиент получает соединение до завершения транзакции, после чего соединение возвращается в пул.

  • * Statement *: Пул агрессивно перезапускает соединения после каждой клиентской инструкции. В режиме выписки транзакции с несколькими выписками не допускаются. Чтобы узнать больше, обратитесь к документации по подключению пулов product.

  • * Размер пула *: количество соединений, которые пул соединений будет держать открытым между собой и базой данных.

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

В этом руководстве мы будем использовать 4 ГБ ОЗУ, 2 виртуальных ЦП, диск 80 ГБ, только для основного узла Настройка управляемой базы данных. В этом разделе вы можете масштабировать параметры теста производительности в соответствии с вашими спецификациями кластера PostgreSQL.

Кластеры управляемой базы данных DigitalOcean имеют параметр PostgreSQL + max_connections +, настроенный на 25 подключений на 1 ГБ ОЗУ. Следовательно, для узла PostgreSQL объемом 4 ГБ ОЗУ + max_connections + установлено равным 100. Кроме того, для всех кластеров 3 соединения зарезервированы для обслуживания. Таким образом, для этого 4 ГБ ОЗУ кластера PostgreSQL доступно 97 соединений для пула соединений.

Имея это в виду, давайте запустим наш первый базовый тест + pgbench +.

Войдите в свой клиентский компьютер. Мы запустим + pgbench +, указав конечную точку базы данных, порт и пользователя как обычно. Кроме того, мы предоставим следующие флаги:

  • + -c +: количество одновременных сеансов клиентов или баз данных для имитации. Мы устанавливаем это значение равным 50, чтобы имитировать количество одновременных соединений, меньших, чем параметр + max_connections + для нашего кластера PostgreSQL.

  • + -j +: количество рабочих потоков, которые + pgbench + будет использовать для запуска теста. Если вы используете многопроцессорную машину, вы можете настроить ее для распределения клиентов по потокам. На двухъядерном компьютере мы устанавливаем это в «+ 2 +».

  • + -P +: отображение прогресса и метрик каждые + 60 + секунд.

  • + -T +: запустить тест на + 600 + секунд (10 минут). Чтобы получить согласованные, воспроизводимые результаты, важно, чтобы вы запустили эталонный тест в течение нескольких минут или через один цикл контрольных точек.

Мы также укажем, что мы хотели бы запустить бенчмарк для базы данных «+ benchmark +», которую мы создали и заполнили ранее.

Выполните следующую полную команду + pgbench +:

pgbench -h  -p 25060 -U doadmin -c 50 -j 2 -P 60 -T 600 benchmark

Нажмите + ENTER + и введите пароль для пользователя + doadmin +, чтобы начать выполнение теста. Вы должны увидеть вывод, подобный следующему (результаты будут зависеть от характеристик вашего кластера PostgreSQL):

Outputstarting vacuum...end.
progress: 60.0 s, 157.4 tps, lat 282.988 ms stddev 40.261
progress: 120.0 s, 176.2 tps, lat 283.726 ms stddev 38.722
progress: 180.0 s, 167.4 tps, lat 298.663 ms stddev 238.124
progress: 240.0 s, 178.9 tps, lat 279.564 ms stddev 43.619
progress: 300.0 s, 178.5 tps, lat 280.016 ms stddev 43.235
progress: 360.0 s, 178.8 tps, lat 279.737 ms stddev 43.307
progress: 420.0 s, 179.3 tps, lat 278.837 ms stddev 43.783
progress: 480.0 s, 178.5 tps, lat 280.203 ms stddev 43.921
progress: 540.0 s, 180.0 tps, lat 277.816 ms stddev 43.742
progress: 600.0 s, 178.5 tps, lat 280.044 ms stddev 43.705
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 150
query mode: simple
number of clients: 50
number of threads: 2
duration: 600 s
number of transactions actually processed: 105256
latency average = 282.039 ms
latency stddev = 84.244 ms
tps = 175.329321 (including connections establishing)
tps = 175.404174 (excluding connections establishing)

Здесь мы заметили, что за 10 минут работы с 50 одновременными сеансами мы обработали 105 256 транзакций с пропускной способностью примерно 175 транзакций в секунду.

Теперь давайте выполним тот же тест, на этот раз с использованием 150 одновременных клиентов, значение для которых выше, чем + max_connections + для этой базы данных, для синтетического моделирования массового притока клиентских подключений:

pgbench -h  -p 25060 -U doadmin -c 150 -j 2 -P 60 -T 600 benchmark

Вы должны увидеть вывод, похожий на следующий:

Outputstarting vacuum...end.
connection to database "pgbench" failed:
FATAL:  remaining connection slots are reserved for non-replication superuser connections
progress: 60.0 s, 182.6 tps, lat 280.069 ms stddev 42.009
progress: 120.0 s, 253.8 tps, lat 295.612 ms stddev 237.448
progress: 180.0 s, 271.3 tps, lat 276.411 ms stddev 40.643
progress: 240.0 s, 273.0 tps, lat 274.653 ms stddev 40.942
progress: 300.0 s, 272.8 tps, lat 274.977 ms stddev 41.660
progress: 360.0 s, 250.0 tps, lat 300.033 ms stddev 282.712
progress: 420.0 s, 272.1 tps, lat 275.614 ms stddev 42.901
progress: 480.0 s, 261.1 tps, lat 287.226 ms stddev 112.499
progress: 540.0 s, 272.5 tps, lat 275.309 ms stddev 41.740
progress: 600.0 s, 271.2 tps, lat 276.585 ms stddev 41.221
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 150
query mode: simple
number of clients: 150
number of threads: 2
duration: 600 s
number of transactions actually processed: 154892
latency average = 281.421 ms
latency stddev = 125.929 ms
tps = 257.994941 (including connections establishing)
tps = 258.049251 (excluding connections establishing)

Обратите внимание на ошибку + FATAL +, указывающую, что + pgbench + превысила пороговое значение ограничения 100 соединений, установленное с помощью + max_connections +, что привело к отказу в соединении. Тест был еще в состоянии завершить, с TPS примерно 257.

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

Шаг 3 - Создание и тестирование пула соединений

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

В общем, настройки + max_connections + и параметры пула соединений настраиваются в тандеме, чтобы максимально увеличить нагрузку на базу данных. Однако, поскольку + max_connections + абстрагируется от пользователя в управляемых базах данных DigitalOcean, нашими основными рычагами здесь являются настройки * Mode * и * Size * пула соединений.

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

Перейдите к * Базы данных * на панели управления, а затем щелкните в своем кластере PostgreSQL. Отсюда, нажмите на * Connection Pools *. Затем нажмите * Создать пул соединений *.

В появившемся окне конфигурации заполните следующие значения:

изображение: https: //assets.digitalocean.com/articles/managed_db_pools/connection_pool_full.png [Значения конфигурации пула подключений]

Здесь мы называем наш пул соединений * test-pool * и используем его с базой данных * benchmark *. Наш пользователь базы данных - * doadmin *, и мы установили пул соединений в режим * Transaction *. Напомним, что для управляемого кластера базы данных с 4 ГБ ОЗУ доступно 97 подключений к базе данных. Соответственно, настройте пул, чтобы поддерживать открытость 97 подключений к базе данных.

Когда вы закончите, нажмите * Создать пул *.

Теперь вы должны увидеть этот пул в панели управления:

изображение: https: //assets.digitalocean.com/articles/managed_db_pools/connection_pool_ui.png [Пул подключений на панели управления]

Захватите его URI, нажав * Сведения о соединении *. Это должно выглядеть примерно так

postgres://doadmin:@:/test-pool?sslmode=require

Здесь вы должны заметить другой порт и, возможно, другую конечную точку и имя базы данных, соответствующее имени пула + test-pool +.

Теперь, когда мы создали пул соединений + test-pool, мы можем перезапустить тест` + pgbench`, который мы запускали выше.

Rerun + pgbench +

На своем клиентском компьютере выполните следующую команду + pgbench + (с 150 одновременными клиентами), убедившись, что выделенные значения заменены значениями в URI пула соединений:

pgbench -h  -p  -U doadmin -c 150 -j 2 -P 60 -T 600 test-pool

Здесь мы снова используем 150 одновременных клиентов, запускаем тест в двух потоках, выполняем печать каждые 60 секунд и запускаем тест в течение 600 секунд. Мы устанавливаем имя базы данных в + test-pool +, имя пула соединений.

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

Outputstarting vacuum...end.
progress: 60.0 s, 240.0 tps, lat 425.251 ms stddev 59.773
progress: 120.0 s, 350.0 tps, lat 428.647 ms stddev 57.084
progress: 180.0 s, 340.3 tps, lat 440.680 ms stddev 313.631
progress: 240.0 s, 364.9 tps, lat 411.083 ms stddev 61.106
progress: 300.0 s, 366.5 tps, lat 409.367 ms stddev 60.165
progress: 360.0 s, 362.5 tps, lat 413.750 ms stddev 59.005
progress: 420.0 s, 359.5 tps, lat 417.292 ms stddev 60.395
progress: 480.0 s, 363.8 tps, lat 412.130 ms stddev 60.361
progress: 540.0 s, 351.6 tps, lat 426.661 ms stddev 62.960
progress: 600.0 s, 344.5 tps, lat 435.516 ms stddev 65.182
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 150
query mode: simple
number of clients: 150
number of threads: 2
duration: 600 s
number of transactions actually processed: 206768
latency average = 421.719 ms
latency stddev = 114.676 ms
tps = 344.240797 (including connections establishing)
tps = 344.385646 (excluding connections establishing)

Обратите внимание, что мы смогли увеличить пропускную способность нашей базы данных с 257 TPS до 344 TPS при 150 одновременных соединениях (увеличение на 33%) и не столкнулись с пределом + max_connections +, который мы ранее достигли без пула соединений. Размещая пул соединений перед базой данных, мы можем избежать разрыва соединений и значительно увеличить пропускную способность базы данных в среде с большим количеством одновременных соединений.

Если вы запустите этот же тест, но со значением + -c + 50 (с указанием меньшего числа клиентов), выгоды от использования пула соединений станут намного менее очевидными:

Outputstarting vacuum...end.
progress: 60.0 s, 154.0 tps, lat 290.592 ms stddev 35.530
progress: 120.0 s, 162.7 tps, lat 307.168 ms stddev 241.003
progress: 180.0 s, 172.0 tps, lat 290.678 ms stddev 36.225
progress: 240.0 s, 172.4 tps, lat 290.169 ms stddev 37.603
progress: 300.0 s, 177.8 tps, lat 281.214 ms stddev 35.365
progress: 360.0 s, 177.7 tps, lat 281.402 ms stddev 35.227
progress: 420.0 s, 174.5 tps, lat 286.404 ms stddev 34.797
progress: 480.0 s, 176.1 tps, lat 284.107 ms stddev 36.540
progress: 540.0 s, 173.1 tps, lat 288.771 ms stddev 38.059
progress: 600.0 s, 174.5 tps, lat 286.508 ms stddev 59.941
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 150
query mode: simple
number of clients: 50
number of threads: 2
duration: 600 s
number of transactions actually processed: 102938
latency average = 288.509 ms
latency stddev = 83.503 ms
tps = 171.482966 (including connections establishing)
tps = 171.553434 (excluding connections establishing)

Здесь мы видим, что мы не смогли увеличить пропускную способность с помощью пула соединений. Наша пропускная способность снизилась до 171 TPS со 175 TPS.

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

Заключение

Пул соединений с управляемыми базами данных DigitalOcean - это мощная функция, которая может помочь вам быстро увеличить производительность вашей базы данных. Наряду с другими методами, такими как репликация, кэширование и разбиение, пул соединений может помочь вам масштабировать уровень базы данных для обработки еще большего объема запросов.

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

Наряду с + pgbench + существуют другие инструменты для тестирования и загрузки вашей базы данных. Одним из таких инструментов, разработанных Percona, является sysbench-tpcc. Другим примером является Apache JMeter, который может загружать тестовые базы данных, а также веб-приложения.

Чтобы узнать больше о управляемых базах данных DigitalOcean, обратитесь к документации по управляемым базам данных product. Чтобы узнать больше о шардинге, еще одном полезном методе масштабирования, обратитесь к Understanding Sharding Database.

Related