Привет, Хабр!

С ростом объёмов данных и увеличением популярности распределённых систем необходимость в анализе распределённых данных становится всё более актуальной. PostgreSQL, благодаря своему мощному функционалу и гибкости, предлагает инструмент, который значительно облегчает эту задачу — Foreign Data Wrappers (FDW).

FDW позволяет подключаться к удалённым базам данных, как если бы они были локальными таблицами. Это удобно для аналитики, интеграции данных из различных источников и упрощает работу с распределёнными системами. FDW поддерживает не только PostgreSQL, но и другие базы данных, такие как MySQL, SQLite и даже API.

Настройка FDW в PostgreSQL

Чтобы начать работать с FDW, первым делом нужно установить необходимое расширение. В нашем случае будем использовать postgres_fdw, которое позволяет подключаться к другим БД PostgreSQL.

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

CREATE EXTENSION IF NOT EXISTS postgres_fdw;

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

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

Создаём сервер:

CREATE SERVER my_remote_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'remote_host', dbname 'remote_db', port '5432');

Здесь my_remote_server — это имя сервера, а remote_host и remote_db — адрес и имя удалённой базы данных соответственно.

Теперь необходимо настроить аутентификацию пользователя, используя маппинг пользователя:

CREATE USER MAPPING FOR local_user
SERVER my_remote_server
OPTIONS (user 'remote_user', password 'remote_password');

Замените local_user, remote_user и remote_password на ваши значения.

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

Создаём внешнюю таблицу:

CREATE FOREIGN TABLE remote_table (
    id SERIAL PRIMARY KEY,
    name TEXT,
    value NUMERIC
)
SERVER my_remote_server
OPTIONS (table_name 'actual_table_name');

Теперь есть remote_table, которая ссылается на таблицу actual_table_name в удалённой базе данных.

Запросы к удалённым данным через FDW

Начнём с самого простого — выполнения запросов к удалённым данным.

Чтобы извлечь данные из удалённой таблицы, выполните:

SELECT * FROM remote_table;

Этот запрос вернёт все строки из удалённой таблицы.

Чтобы уменьшить количество возвращаемых данных и ускорить обработку, добавим фильтр:

SELECT * FROM remote_table WHERE value > 100;

Здесь мы получаем только те записи, где value больше 100.

FDW позволяет выполнять JOIN с локальными таблицами. Рассмотрим, как это сделать:

SELECT l.id, l.name, r.value
FROM local_table l
JOIN remote_table r ON l.id = r.id
WHERE r.value > 100;

Этот запрос объединяет данные из локальной таблицы local_table и удалённой remote_table, фильтруя результаты по значению value.

После выполнения запроса вы можете обрабатывать данные, как обычно, используя стандартные функции PostgreSQL. Например, чтобы вычислить среднее значение:

WITH filtered_data AS (
    SELECT name, value
    FROM remote_table
    WHERE value > 100
)
SELECT AVG(value) AS avg_value FROM filtered_data;

В этом примере сначала фильтруем данные, а затем вычисляем среднее значение.

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

SELECT COUNT(*) FROM remote_table WHERE value IS NOT NULL;

FDW не ограничивается только PostgreSQL. Можно подключаться к другим базам данных, таким как MySQL или SQLite, используя соответствующие FDW-расширения. Например, для подключения к MySQL используйте mysql_fdw:

CREATE EXTENSION IF NOT EXISTS mysql_fdw;

CREATE SERVER my_mysql_server
FOREIGN DATA WRAPPER mysql_fdw
OPTIONS (host 'mysql_host', port '3306');

Затем создаем маппинг пользователя и внешние таблицы так же, как мы сделали это для PostgreSQL.

Заключение

Foreign Data Wrappers позволяет интегрировать данные из различных источников, упрощая анализ и управление.

Как вы используете FDW в своих проектах? Поделитесь опытом в комментариях!


А изучить современные принципы и практики архитектуры, эффективное управление командой аналитиков, тенденции на международном рынке можно на онлайн-курсе «Системный аналитик. Team Lead».

Комментарии (5)


  1. Akina
    25.09.2024 18:26
    +1

    Нет, а про самое важное сказать? ГДЕ выполняется код? скажем, вот приведённый код:

    SELECT l.id, l.name, r.value
    FROM local_table l
    JOIN remote_table r ON l.id = r.id
    WHERE r.value > 100;

    Что будет запрошено с удалённого сервера? Какой фактически запрос выполнит удалённый сервер и какой набор данных передаст нам для получения результирующего датасета? И как то же самое дело обстоит в случае, когда удалённый сервер - не PostgreSQL? А то, может, с удалённого сервера и нужна-то всего одна запись, а мы поволочём по сети гигабайтами...

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

    Так как же оно на самом деле?

    PS. И кстати... где в статье ну хоть что-нибудь про анализ? кроме заглавия, конечно.


    1. gudvinr
      25.09.2024 18:26

      Если коротко, это зависит от конкретного драйвера. Какого-то общего правила нет.

      Но постгрес возможность сократить выборку представляет:
      https://www.postgresql.org/docs/current/postgres-fdw.html#POSTGRES-FDW-REMOTE-QUERY-OPTIMIZATION


      1. Akina
        25.09.2024 18:26

        Но постгрес возможность сократить выборку представляет

        Если ориентироваться на описание, то на удалённый сервер при выполнении процитированного запроса поступит либо такое:

        SELECT id, value
        FROM table_on_remote_server
        WHERE value > 100

        либо вообще вот такое:

        SELECT id, value
        FROM table_on_remote_server
        WHERE value > 100
          AND id IN ( {список id из таблицы локального сервера} )

        В зависимости от статистики более выгодным может оказаться либо первый, либо второй вариант. Хотя что-то мне подсказывает, что статистика удалённых данных локальному серверу недоступна, так что исходного материала для анализа и выбора у него не будет. И если список id не сильно пухлый, то разумнее, наверное, отправлять второй вариант.

        Можно ли в этом убедиться? например, в MySQL я могу без проблем включить на удалённом сервере General Log и получить полный и точный список всех команд, которые пришли от враппера... увы, ни самого постгресса, ни знаний, как это сделать в постгрессе, у меня нет.

        PS. Опять же ориентируясь на описание, полагаю, что управлять такими тонкостями работы враппера - невозможно. Хотя можно, ориентируясь на знание реальной статистики данных, попробовать хинтануть текстом запроса.


        1. gudvinr
          25.09.2024 18:26

          Хотя что-то мне подсказывает, что статистика удалённых данных локальному серверу недоступна

          Она доступна настолько, насколько конкретный драйвер это позволяет. API для FDW позволяет определить колбеки, которые позволяют драйверу сообщить планировщику постгреса о ситуации на удалённой стороне.

          Для MySQL есть mysql_fdw:

          • The where condition on the foreign table will be executed on the foreign server hence there will be fewer rows to bring across to PostgreSQL

          • The latest version does the column push-down and only brings back the columns that are part of the select target list

          • The joins between two foreign tables from the same remote MySQL server are pushed to a remote server

          Ну и т.д.


          1. Akina
            25.09.2024 18:26

            Она доступна настолько, насколько конкретный драйвер это позволяет.

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

            Обратимся к примеру выше. Если список id содержит 1000 значений, а удалённая таблица - 30 записей, то разумнее WHERE IN обрабатывать локально, а если в удалённой таблице 100к записей, и в среднем по 5 значений на каждый id - то лучше отправить список туда для удалённой обработки. И вот мне сильно сомнительно, что планировщик получает через драйвер всю статистику данных (количество записей, кардинальность) на удалённом сервере и использует её при построении плана.

            Хотя чего только не бывает...