21.2. Подключение и работа с кластером Postgres Pro Shardman #
Кластер состоит из четырёх сегментов. Cекции данных основной сегментированной таблицы распределяются по остальным сегментам таким образом:
Для ключа сегментирования ticket_no:
tickets_0— сегмент-1 (узел кластераnode1)tickets_1— сегмент-2 (узел кластераnode2)tickets_2— сегмент-3 (узел кластераnode3)tickets_3— сегмент-4 (узел кластераnode4)
Для ключа сегментирования book_ref:
bookings_0— сегмент-1 (узел кластераnode1)bookings_1— сегмент-2 (узел кластераnode2)bookings_2— сегмент-3 (узел кластераnode3)bookings_3— сегмент-4 (узел кластераnode4)
Ниже приведены примеры для ключа сегментирования book_ref, но указанный в подразделах код будет справедлив и для ключа сегментирования ticket_no.
Не стоит рассматривать данный код как оптимальный или пригодный для производственной среды. Он дан только как пример реализации создания пула соединений для работы с кластером Postgres Pro Shardman.
Общее для всех приведённых примеров — строка подключения к кластеру, которая должна содержать имена узлов, номера TCP-портов, имя и пароль пользователя, имя базы данных для подключения и набор параметров сеанса.
Такую строку можно получить с помощью утилиты shardmanctl. В простейшем случае строка будет выглядеть так:
$ shardmanctl getconnstr dbname=postgres host=node1,node2,node3,node4 port=5432,5432,5432,5432
Её можно использовать для подключения к узлам кластера или для создания пула соединений в приложениях.
21.2.1. SQL #
В Postgres Pro Shardman реализовано несколько удобных функций и представлений для наблюдения за кластером:
Вывод списка глобальных таблиц
Вывод списка сегментированная таблиц
Вывод списка глобальных последовательностей
Вычисление номера сегмента по ключу сегментирования
Выполнение
ANALYZEдля всех глобальных и сегментированных таблиц в кластере
21.2.1.1. Отображение списка глобальных таблиц #
Для вывода всех глобальных таблиц в кластере используйте представление shardman.global_tables:
postgres=# select
relname as table_name,
nspname as schema
from shardman.global_tables;
table_name | schema
------------+----------
aircrafts | bookings
seats | bookings
airports | bookings
flights | bookings
(4 rows)
21.2.1.2. Отображение списка сегментированная таблиц #
Для получения сведений обо всех сегментированных таблицах в кластере выполните запрос к представлению shardman.sharded_tables как показано ниже:
postgres=# select
relname as table_name,
nparts as partitions,
colocated_with::oid::regclass::text as colocated_with,
nspname as schema
from shardman.sharded_tables;
table_name | partitions | colocated_with | schema
-----------------+------------+----------------+----------
bookings | 4 | | bookings
ticket_flights | 4 | bookings | bookings
tickets | 4 | bookings | bookings
boarding_passes | 4 | bookings | bookings
(4 rows)
21.2.1.3. Отображение списка глобальных последовательностей #
Для вывода всех глобальных последовательностей в кластере используйте представление shardman.sequence:
postgres=# select
seqns as schema,
seqname as sequence_name,
seqmin as min_value,
seqmax as max_value,
seqblk as bulk_size
from shardman.sequence;
schema | sequence_name | min_value | max_value | bulk_size
----------+-------------------------+-----------+---------------------+-----------
bookings | flights_flight_id_seq | 262145 | 9223372036854775807 | 65536
(1 rows)
21.2.1.4. Вычисление номера сегмента по ключу сегментирования #
Для вывода имени секции, содержащей данные и имя группы репликации вызовите функцию shardman.get_partition_for_value(). Например, пусть book_ref = 0369E5:
postgres=# select * from shardman.get_partition_for_value(
'bookings'::regclass,
'0369E5'::character(6));
rgid | local_nspname | local_relname | remote_nspname | remote_relname
------+---------------+---------------+----------------+----------------
1 | bookings | bookings_0 | bookings | bookings_0
Этот вывод показывает, что данные в секции bookings_0 таблицы bookings расположены в том же узле, в котором выполнялся запрос.
Выполните запрос, показывающий имя сервера, где находится секция с данными. Если подключиться к серверу, содержащему искомую секцию, то в выводе имени сервера будет написано «current server» (текущий сервер). Если данные расположены в другом сегменте, показывается имя узла мастера сегмента:
SELECT p.rgid,
local_relname AS partition_name,
CASE
WHEN r.srvid IS NULL THEN 'current server'
ELSE (SELECT (SELECT split_part(kv, '=', 2)
FROM (SELECT unnest(fs.srvoptions) as kv) x
WHERE split_part(kv, '=', 1) = 'host')
FROM shardman.repgroups rg
JOIN pg_catalog.pg_foreign_server AS fs ON fs.oid = rg.srvid
WHERE rg.id = p.rgid)
END AS server_name
FROM shardman.get_partition_for_value('bookings'::regclass, '0369E5'::character(6)) p
JOIN shardman.repgroups AS r ON
r.id = p.rgid;
rgid | partition_name | server_name
------+----------------+----------------
1 | bookings_0 | current server
(1 row)
При выполнении запроса с другим ключом сегментирования — 0369E6 — результат будет таким:
rgid | partition_name | server_name
------+----------------+-------------
4 | bookings_3_fdw | node4
(1 row)
Видно, что секция находится на узле node4.
Также обратите внимание, что параметр shardman.rgid позволяет вам найти номер узла с сеансом подключения. Для этого выполните следующий запрос:
SELECT pg_catalog.current_setting('shardman.rgid');
Это значение можно использовать для определения расположения секций в подобных запросах.
Функция shardman.get_partition_for_value() в основном предназначена для административных целей и лучшего понимания топологии данных.
Как правило, административные функции не следует использовать при написании SQL-кода для доступа к данным.
21.2.1.5. Расположение секций сегментированных таблиц по сегментам #
Список всех сегментированных таблиц в схеме bookings, количество их секций и распределение по серверам (сегментам) можно получить из метаданных Postgres Pro Shardman на любом узле кластера.
Рассмотрим следующий запрос:
SELECT p.rel::regclass::text AS table_name,
p.pnum,
p.rgid,
r.srvid,
fs.srvname
FROM shardman.parts p
JOIN shardman.repgroups r
ON p.rgid = r.id
LEFT OUTER JOIN pg_foreign_server fs
ON r.srvid = fs.oid;
Чтобы выяснить как распределены данные, объедините этот запрос с подзапросом из Раздел 21.2.1.4:
SELECT p.rel::regclass AS table_name,
st.nparts AS total_parts,
p.pnum AS num_part,
CASE
WHEN r.srvid IS NULL THEN 'connected server'
ELSE
(SELECT split_part(kv, '=', 2)
FROM (SELECT unnest(fs.srvoptions) AS kv) x
WHERE split_part(kv, '=', 1) = 'host')
END AS server_name
FROM shardman.parts p
JOIN shardman.repgroups r
ON p.rgid = r.id
LEFT JOIN shardman.sharded_tables st
ON p.rel = st.rel
LEFT JOIN pg_foreign_server fs
ON r.srvid = fs.oid
WHERE st.nspname = 'bookings'
ORDER BY table_name, num_part, server_name;
Формат вывода результата: имя таблицы, количество секций в таблице, номер секции и имя сервера:
table_name | total_parts | num_part | server_name
--------------------------+-------------+----------+------------------
bookings.bookings | 4 | 0 | connected server
bookings.bookings | 4 | 1 | node2
bookings.bookings | 4 | 2 | node3
bookings.bookings | 4 | 3 | node4
bookings.ticket_flights | 4 | 0 | connected server
bookings.ticket_flights | 4 | 1 | node2
bookings.ticket_flights | 4 | 2 | node3
bookings.ticket_flights | 4 | 3 | node4
bookings.tickets | 4 | 0 | connected server
bookings.tickets | 4 | 1 | node2
bookings.tickets | 4 | 2 | node3
bookings.tickets | 4 | 3 | node4
bookings.boarding_passes | 4 | 0 | connected server
bookings.boarding_passes | 4 | 1 | node2
bookings.boarding_passes | 4 | 2 | node3
bookings.boarding_passes | 4 | 3 | node4
21.2.1.6. Сбор статистики #
Для сбора статистики по сегментированным и глобальным таблицам вызовите функцию shardman.global_analyze(). Сначала эта функция выполняет сбор статистики для всех локальных секций распределённых таблиц на каждом узле, а затем транслирует эту статистику на другие узлы. Для глобальной таблицы будет выполнен сбор статистики на одном выбранном узле, после чего собранная статистика транслируется на все остальные узлы кластера.