22.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
   

Её можно использовать для подключения к узлам кластера или для создания пула соединений в приложениях.

22.2.1. SQL #

В Postgres Pro Shardman реализовано несколько удобных функций и представлений для наблюдения за кластером:

  • Вывод списка глобальных таблиц

  • Вывод списка сегментированная таблиц

  • Вывод списка глобальных последовательностей

  • Вычисление номера сегмента по ключу сегментирования

  • Выполнение ANALYZE для всех глобальных и сегментированных таблиц в кластере

22.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)
   

22.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)
   

22.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)
   

22.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-кода для доступа к данным.

22.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;
   

Чтобы выяснить как распределены данные, объедините этот запрос с подзапросом из Раздел 22.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

22.2.1.6. Сбор статистики #

Для сбора статистики по сегментированным и глобальным таблицам вызовите функцию shardman.global_analyze(). Сначала эта функция выполняет сбор статистики для всех локальных секций распределённых таблиц на каждом узле, а затем транслирует эту статистику на другие узлы. Для глобальной таблицы будет выполнен сбор статистики на одном выбранном узле, после чего собранная статистика транслируется на все остальные узлы кластера.