Привет, Хабр!
С ростом объёмов данных и увеличением популярности распределённых систем необходимость в анализе распределённых данных становится всё более актуальной. 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».
Akina
Нет, а про самое важное сказать? ГДЕ выполняется код? скажем, вот приведённый код:
Что будет запрошено с удалённого сервера? Какой фактически запрос выполнит удалённый сервер и какой набор данных передаст нам для получения результирующего датасета? И как то же самое дело обстоит в случае, когда удалённый сервер - не PostgreSQL? А то, может, с удалённого сервера и нужна-то всего одна запись, а мы поволочём по сети гигабайтами...
Самый плохой случай - это когда весь набор данных тянется "на себя", а потом обрабатывается согласно тексту запроса. Самый хороший - когда максимально возможный отбор и обработка отдаются на удалённый сервер, там выполняются, и получаются уже минимизированные по объёму и предобработанные данные для финальной обработки. Правда, этот вариант кажется мне маловероятным, особенно в случае, когда на удалении совсем другая СУБД - элементарно синтаксические различия могут привести к тому, что на удалённом сервере просто нет соответствующих функций.
Так как же оно на самом деле?
PS. И кстати... где в статье ну хоть что-нибудь про анализ? кроме заглавия, конечно.
gudvinr
Если коротко, это зависит от конкретного драйвера. Какого-то общего правила нет.
Но постгрес возможность сократить выборку представляет:
https://www.postgresql.org/docs/current/postgres-fdw.html#POSTGRES-FDW-REMOTE-QUERY-OPTIMIZATION
Akina
Если ориентироваться на описание, то на удалённый сервер при выполнении процитированного запроса поступит либо такое:
либо вообще вот такое:
В зависимости от статистики более выгодным может оказаться либо первый, либо второй вариант. Хотя что-то мне подсказывает, что статистика удалённых данных локальному серверу недоступна, так что исходного материала для анализа и выбора у него не будет. И если список id не сильно пухлый, то разумнее, наверное, отправлять второй вариант.
Можно ли в этом убедиться? например, в MySQL я могу без проблем включить на удалённом сервере General Log и получить полный и точный список всех команд, которые пришли от враппера... увы, ни самого постгресса, ни знаний, как это сделать в постгрессе, у меня нет.
PS. Опять же ориентируясь на описание, полагаю, что управлять такими тонкостями работы враппера - невозможно. Хотя можно, ориентируясь на знание реальной статистики данных, попробовать хинтануть текстом запроса.
gudvinr
Она доступна настолько, насколько конкретный драйвер это позволяет. 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
Ну и т.д.
Akina
Я имел в виду получение статистики данных удалённой таблицы, которая используется планировщиком при построении плана.
Обратимся к примеру выше. Если список id содержит 1000 значений, а удалённая таблица - 30 записей, то разумнее WHERE IN обрабатывать локально, а если в удалённой таблице 100к записей, и в среднем по 5 значений на каждый id - то лучше отправить список туда для удалённой обработки. И вот мне сильно сомнительно, что планировщик получает через драйвер всю статистику данных (количество записей, кардинальность) на удалённом сервере и использует её при построении плана.
Хотя чего только не бывает...