PostgreSQL FDW: Tuyệt chiêu truy vấn MySQL, MongoDB và CSV trực tiếp không cần ETL

Database tutorial - IT technology blog
Database tutorial - IT technology blog

Tại sao Foreign Data Wrappers (FDW) lại là cứu cánh?

Dữ liệu “phân mảnh” là nỗi ám ảnh thường trực của mọi developer. Hãy tưởng tượng: thông tin user nằm ở MySQL, log hoạt động kẹt trong MongoDB, còn danh sách khuyến mãi lại nằm trong một file CSV 500MB do team Marketing gửi qua Slack. Cách làm cũ là viết script Python hoặc dựng pipeline ETL cồng kềnh để gom dữ liệu về một mối. Tuy nhiên, việc bảo trì đống pipeline này cực kỳ tốn sức.

Tôi từng nhận task migrate hệ thống báo cáo từ MySQL sang PostgreSQL. Thay vì tốn 3 ngày viết tool đồng bộ, tôi chỉ mất đúng 45 phút cấu hình Foreign Data Wrappers (FDW). FDW biến PostgreSQL thành một “Data Hub” thực thụ. Bạn có thể JOIN trực tiếp giữa bảng Postgres local và bảng MySQL từ xa như thể chúng đang nằm chung một database. Dữ liệu được truy vấn bằng cú pháp SQL chuẩn mà không cần copy bất kỳ byte nào về máy local.

Lợi thế lớn nhất ở đây là tính tức thời. MySQL vừa có đơn hàng mới là bên Postgres thấy ngay, không cần đợi job ETL chạy định kỳ. FDW không phải giải pháp vạn năng cho mọi bài toán hiệu năng. Nhưng để làm báo cáo nhanh, migration hoặc đối soát dữ liệu, nó thực sự là một “vũ khí” lợi hại.

Cài đặt các Extension cần thiết

PostgreSQL mặc định chỉ có sẵn postgres_fdw để kết nối giữa các server Postgres. Để vươn vòi sang MySQL hay MongoDB, bạn cần cài thêm driver tương ứng từ repository của hệ điều hành. Trên Ubuntu, hãy chạy lệnh sau:

# Cài đặt thư viện hỗ trợ cho MySQL và CSV
sudo apt-get install postgresql-15-mysql-fdw
sudo apt-get install postgresql-15-mongo-fdw

Sau khi cài đặt ở mức OS, hãy đăng nhập vào Postgres với quyền superuser để kích hoạt extension. Đây là bước bắt buộc để database nhận diện được các wrapper mới.

-- Kích hoạt extension
CREATE EXTENSION mysql_fdw;
CREATE EXTENSION file_fdw;
CREATE EXTENSION mongo_fdw;

Cấu hình chi tiết cho từng nguồn dữ liệu

1. Kết nối với MySQL

Đây là kịch bản phổ biến nhất trong thực tế. Quy trình thiết lập gồm 4 bước rõ ràng: khai báo server, map user và import bảng.

-- Bước 1: Khai báo server MySQL từ xa
CREATE SERVER mysql_server 
FOREIGN DATA WRAPPER mysql_fdw 
OPTIONS (host '192.168.1.50', port '3306');

-- Bước 2: Map user Postgres hiện tại với user MySQL
CREATE USER MAPPING FOR current_user 
SERVER mysql_server 
OPTIONS (username 'db_user', password 'secure_password');

-- Bước 3: Import toàn bộ schema để tiết kiệm thời gian
IMPORT FOREIGN SCHEMA production_db 
FROM SERVER mysql_server 
INTO local_mysql_schema;

2. Đọc file CSV dung lượng lớn

Sếp quăng cho bạn file CSV 5GB và yêu cầu đối soát dữ liệu ngay lập tức? Thay vì dùng lệnh COPY tốn dung lượng ổ cứng, hãy dùng file_fdw để đọc trực tiếp từ file.

-- Khởi tạo server cho file
CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw;

-- Tạo bảng ảo liên kết với file CSV
CREATE FOREIGN TABLE csv_logs (
    log_date date,
    log_level text,
    message text
) SERVER file_server 
OPTIONS (filename '/var/lib/postgresql/data/logs.csv', format 'csv', header 'true');

-- Query trực tiếp như bảng bình thường
SELECT log_level, count(*) FROM csv_logs GROUP BY 1;

3. Kết nối với MongoDB (NoSQL)

Việc ép kiểu từ Document sang Relational đôi khi hơi phiền phức. mongo_fdw xử lý việc này bằng cách map các field trong BSON thành các cột cố định trong Postgres.

-- Cấu hình server MongoDB
CREATE SERVER mongo_server 
FOREIGN DATA WRAPPER mongo_fdw 
OPTIONS (address '127.0.0.1', port '27017');

-- Ánh xạ collection thành foreign table
CREATE FOREIGN TABLE mongo_logs (
    _id text,
    user_id int,
    action text
) SERVER mongo_server 
OPTIONS (db 'app_logs', collection 'activity_logs');

Chiến thuật tối ưu hiệu suất và bảo mật

Sai lầm phổ biến nhất là coi Foreign Table như bảng local. Hãy nhớ rằng network luôn là nút thắt cổ chai lớn nhất. Nếu bạn JOIN hai bảng MySQL và Postgres có hàng triệu record, băng thông server sẽ sớm bị nghẽn.

Tận dụng Predicate Pushdown

Pushdown là tính năng sống còn của FDW. Khi bạn viết WHERE id = 10, Postgres sẽ đẩy điều kiện này sang phía MySQL để lọc trước. Điều này giúp giảm lượng dữ liệu truyền tải qua mạng. Hãy luôn dùng EXPLAIN ANALYZE để kiểm tra câu query.

EXPLAIN ANALYZE 
SELECT p.name, m.email 
FROM local_products p 
JOIN remote_users m ON p.user_id = m.id 
WHERE m.status = 'active';

Nếu thấy dòng Remote SQL trong kết quả, nghĩa là Pushdown đang hoạt động. Ngược lại, nếu Postgres kéo toàn bộ bảng về rồi mới lọc, server của bạn sẽ sớm “khóc thét”.

Lưu ý về an toàn dữ liệu

Thông tin password trong USER MAPPING được lưu ở metadata. Bạn chỉ nên cấp quyền USAGE cho những user thực sự cần thiết. Một mẹo nhỏ là luôn dùng tài khoản Read-Only ở phía source (MySQL/Mongo). Cách này giúp tránh rủi ro lỡ tay chạy lệnh DELETE làm bay màu dữ liệu gốc.

Tóm lại, FDW giúp kiến trúc dữ liệu gọn gàng và linh hoạt hơn nhiều. Nó giải quyết bài toán dữ liệu phân tán mà không cần duy trì các pipeline ETL phức tạp. Nếu bạn đang đối mặt với hệ thống đa nguồn, hãy thử setup FDW ngay hôm nay.

Share: