PostgreSQL
Foreign Data Wrappers
Что если обратиться к MySQL, S3-файлам и удалённому PostgreSQL одним SQL-запросом, без ETL и промежуточных таблиц?
- Cloudflare агрегирует метрики из 250+ PoP через postgres_fdw без ETL-конвейеров
- Supabase предоставляет parquet_s3_fdw пользователям для SQL-запросов к S3 без отдельного аналитического движка
- GitHub выполняет параллельные запросы к 12 региональным кластерам через async FDW, сокращая время агрегации с 12 до 1.5 секунды
Концепция FDW
Foreign Data Wrappers (FDW) - это SQL/MED стандарт (ISO/IEC 9075-9), реализованный в PostgreSQL с версии 9.1. FDW позволяет обращаться к внешним источникам данных через стандартный SQL-интерфейс, как если бы они были локальными таблицами.
Архитектура FDW состоит из трёх уровней: Foreign Server (адрес и параметры подключения к источнику), User Mapping (маппинг локальных пользователей на учётные данные источника) и Foreign Table (виртуальная таблица, представляющая внешние данные).
PostgreSQL содержит реестр расширений-обёрток: file_fdw (встроен), postgres_fdw (встроен), а также сторонние: mysql_fdw, oracle_fdw, mongo_fdw, redis_fdw, parquet_s3_fdw и десятки других.
Cloudflare использует FDW для консолидации метрик из 250+ PoP-точек в центральную аналитическую базу без ETL-конвейеров. Каждый региональный PostgreSQL-кластер доступен через postgres_fdw с query pushdown - запросы с фильтрами по дате и региону передаются на удалённый сервер, а не вытягивают весь объём данных.
Какой стандарт лежит в основе FDW в PostgreSQL?
FDW реализует стандарт SQL/MED (Management of External Data), часть 9 стандарта ISO/IEC 9075.
postgres_fdw
postgres_fdw - самый функциональный FDW в экосистеме, поддерживает полный query pushdown: фильтры WHERE, JOIN, сортировку ORDER BY, агрегаты COUNT/SUM и даже UPDATE/DELETE на удалённых таблицах (начиная с PostgreSQL 9.3).
IMPORT FOREIGN SCHEMA - удобная альтернатива ручному CREATE FOREIGN TABLE. Синхронизирует структуру таблиц с удалённым сервером за одну команду.
Notion применяет postgres_fdw для федерации данных между шардами. При запросе workspace-метаданных, разбросанных по нескольким шардам, использование FDW с async_capable позволило сократить время ответа на 60% по сравнению с application-level aggregation - параллельные запросы выполняются одновременно.
postgres_fdw не поддерживает транзакции 2PC между локальным и удалённым серверами. Если транзакция успешно зафиксирована локально, но сеть упала до фиксации на удалённом - возникает partial commit. Для критичных операций использовать компенсирующие транзакции или saga-паттерн.
Что такое 'query pushdown' в контексте postgres_fdw?
Pushdown передаёт WHERE, GROUP BY, ORDER BY на удалённый сервер - данные фильтруются там, а не передаются целиком для локальной фильтрации.
mysql_fdw и другие сторонние FDW
mysql_fdw (EnterpriseDB) обеспечивает read/write доступ к MySQL и MariaDB из PostgreSQL. Поддерживает pushdown фильтров и сортировок, маппинг типов данных. Используется для миграции с MySQL или работы с legacy-системами.
Популярные сторонние FDW: oracle_fdw (Laurenz Albe) для Oracle Database, tds_fdw для MS SQL Server и Sybase, mongo_fdw для MongoDB, redis_fdw для Redis, parquet_s3_fdw для Parquet-файлов на S3, multicorn для написания FDW на Python.
Supabase использует parquet_s3_fdw в своём продукте Supabase Analytics - пользователи могут запрашивать данные из S3 через обычный SQL, без необходимости разворачивать отдельный аналитический движок.
Какой FDW позволяет запрашивать Parquet-файлы на S3 через SQL?
parquet_s3_fdw специализируется на работе с Parquet-файлами в S3-совместимых хранилищах через стандартный SQL-интерфейс.
file_fdw
file_fdw - встроенное расширение PostgreSQL для чтения файлов через SQL. Поддерживает CSV, TSV и любые форматы, совместимые с COPY FROM. Полезно для импорта данных из файловой системы без промежуточных этапов.
file_fdw предоставляет доступ только суперпользователю или пользователям с ролью pg_read_server_files. Файл читается с правами процесса PostgreSQL (обычно postgres), поэтому доступны только файлы, читаемые этим пользователем.
file_fdw удобен для разбора CSV-экспортов из других систем прямо в SQL-запросах, без необходимости создавать промежуточные таблицы через COPY.
Типичный use case: анализ PostgreSQL CSV-логов для обнаружения паттернов медленных запросов. Команда Dropbox использовала этот подход для ежедневного парсинга логов из 800+ инстансов: file_fdw + UNION ALL + агрегация дают отчёт о топ-100 медленных запросов за 5 минут без внешних инструментов.
Какой формат файлов поддерживает file_fdw?
file_fdw использует механизм COPY FROM, поэтому поддерживает все форматы, совместимые с этой командой: CSV, TSV, custom delimiter.
Query Pushdown и производительность FDW
Query pushdown - ключевой механизм производительности FDW. Планировщик PostgreSQL анализирует запрос и определяет, какие части можно выполнить на удалённом сервере, чтобы минимизировать объём передаваемых данных.
Факторы, блокирующие pushdown: локальные функции (не существующие на удалённом сервере), несовместимые типы данных, collation-конфликты, оператор ANY с локальным массивом. EXPLAIN VERBOSE покажет строку 'Remote SQL' - если её нет, pushdown не происходит.
GitHub использует postgres_fdw с async_capable для параллельного опроса 12 региональных PostgreSQL-кластеров при генерации глобальных отчётов. Асинхронный режим позволяет выполнять все 12 запросов параллельно, сокращая время агрегации с 12 секунд до 1.5 секунды.
При архитектуре с FDW стоит создавать STATISTICS на foreign tables через ANALYZE - планировщик сможет лучше оценить стоимость удалённых запросов и принять правильное решение о порядке JOIN.
FDW - это просто прозрачная репликация данных
FDW обеспечивает виртуальный доступ к внешним данным без их физического копирования. Данные остаются на источнике, каждый запрос выполняется через сетевое соединение. Для частых запросов к большим объёмам имеет смысл рассмотреть материализованные представления поверх FDW с периодическим REFRESH.
FDW обеспечивает виртуальный доступ через сетевые запросы при каждом обращении. Для частых запросов к большим объёмам имеет смысл создать материализованное представление поверх FDW с периодическим REFRESH - это локально кэшируует результаты.
Что блокирует query pushdown в postgres_fdw?
Локальные функции (UDF) нельзя выполнить на удалённом сервере, поэтому строки передаются локально для обработки. WHERE/GROUP BY/ORDER BY с встроенными функциями поддерживают pushdown.
Foreign Data Wrappers
- FDW реализует SQL/MED стандарт: внешние источники выглядят как локальные таблицы
- postgres_fdw поддерживает полный pushdown WHERE/GROUP BY/ORDER BY на удалённый PostgreSQL
- mysql_fdw, parquet_s3_fdw, mongo_fdw расширяют доступ к гетерогенным источникам
- file_fdw читает CSV/TSV файлы через SQL без промежуточного COPY
- EXPLAIN VERBOSE показывает 'Remote SQL' - признак работающего pushdown
Связь с другими темами
FDW дополняет другие подходы к работе с распределёнными данными
- Citus — Citus - горизонтальное масштабирование внутри PostgreSQL, FDW - доступ к внешним гетерогенным источникам
- Логическая репликация — Логическая репликация копирует данные для локального хранения; FDW предоставляет виртуальный доступ без копирования
- Материализованные представления — Matview поверх FDW-таблицы кэширует результаты удалённых запросов локально для повышения производительности
Вопросы для размышления
- Когда предпочесть FDW вместо ETL-конвейера для интеграции с внешними системами?
- Почему локальные UDF блокируют query pushdown и как это влияет на производительность?
- Какие риски несёт запись в удалённые таблицы через FDW при сбое сети в момент транзакции?