EnterpriseDB / mysql_fdw

PostgreSQL foreign data wrapper for MySQL
Other
521 stars 160 forks source link

MySQL Foreign Data Wrapper for PostgreSQL

This is a foreign data wrapper (FDW) to connect PostgreSQL to MySQL.

Please note that this version of mysql_fdw works with PostgreSQL and EDB Postgres Advanced Server 12, 13, 14, 15, 16, and 17.

Contents

  1. Features
  2. Supported platforms
  3. Installation
  4. Usage
  5. Functions
  6. Generated columns
  7. Examples
  8. Limitations
  9. Contributing
  10. Support
  11. Useful links
  12. License

Features

Common features & enhancements

The following enhancements are added to the latest version of mysql_fdw:

Write-able FDW

The previous version was only read-only, the latest version provides the write capability. The user can now issue an insert, update, and delete statements for the foreign tables using the mysql_fdw. It uses the PG type casting mechanism to provide opposite type casting between MySQL and PG data types.

Connection Pooling

The latest version comes with a connection pooler that utilises the same MySQL database connection for all the queries in the same session. The previous version would open a new MySQL database connection for every query. This is a performance enhancement.

Prepared Statement

(Refactoring for select queries to use prepared statement)

The select queries are now using prepared statements instead of simple query protocol.

Pushdowning

WHERE clause push-down

The latest version will push-down the foreign table where clause to the foreign server. 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. This is a performance feature.

Column push-down

The previous version was fetching all the columns from the target foreign table. The latest version does the column push-down and only brings back the columns that are part of the select target list. This is a performance feature.

JOIN push-down

mysql_fdw now also supports join push-down. The joins between two foreign tables from the same remote MySQL server are pushed to a remote server, instead of fetching all the rows for both the tables and performing a join locally, thereby enhancing the performance. Currently, joins involving only relational and arithmetic operators in join-clauses are pushed down to avoid any potential join failure. Also, only the INNER and LEFT/RIGHT OUTER joins are supported, and not the FULL OUTER, SEMI, and ANTI join. This is a performance feature.

AGGREGATE push-down

mysql_fdw now also supports aggregate push-down. Push aggregates to the remote MySQL server instead of fetching all of the rows and aggregating them locally. This gives a very good performance boost for the cases where aggregates can be pushed down. The push-down is currently limited to aggregate functions min, max, sum, avg, and count, to avoid pushing down the functions that are not present on the MySQL server. Also, aggregate filters and orders are not pushed down.

ORDER BY push-down

mysql_fdw now also supports order by push-down. If possible, push order by clause to the remote server so that we get the ordered result set from the foreign server itself. It might help us to have an efficient merge join. NULLs behavior is opposite on the MySQL server. Thus to get an equivalent result, we add the "expression IS NULL" clause at the beginning of each of the ORDER BY expressions.

LIMIT OFFSET push-down

mysql_fdw now also supports limit offset push-down. Wherever possible, perform LIMIT and OFFSET operations on the remote server. This reduces network traffic between local PostgreSQL and remote MySQL servers. ALL/NULL options are not supported on the MySQL server, and thus they are not pushed down. Also, OFFSET without LIMIT is not supported on the MySQL server hence queries having that construct are not pushed.

Supported platforms

mysql_fdw was developed on Linux, and should run on any reasonably POSIX-compliant system.

Please refer to mysql_fdw_documentation.

Installation

Prerequisites

To compile the MySQL foreign data wrapper, MySQL's C client library is needed. This library can be downloaded from the official MySQL website.

Source installation

  1. To build on POSIX-compliant systems you need to ensure the pg_config executable is in your path when you run make. This executable is typically in your PostgreSQL installation's bin directory. For example:

    $ export PATH=/usr/local/pgsql/bin/:$PATH
  2. The mysql_config must also be in the path, it resides in the MySQL bin directory.

    $ export PATH=/usr/local/mysql/bin/:$PATH
  3. Compile the code using make.

    $ make USE_PGXS=1
  4. Finally install the foreign data wrapper.

    $ make USE_PGXS=1 install
  5. Running regression test.

    $ make USE_PGXS=1 installcheck

    However, make sure to set the MYSQL_HOST, MYSQL_PORT, MYSQL_USER_NAME, and MYSQL_PWD environment variables correctly. The default settings can be found in the mysql_init.sh script.

If you run into any issues, please let us know.

Usage

CREATE SERVER options

mysql_fdw accepts the following options via the CREATE SERVER command:

CREATE USER MAPPING options

mysql_fdw accepts the following options via the CREATE USER MAPPING command:

CREATE FOREIGN TABLE options

mysql_fdw accepts the following table-level options via the CREATE FOREIGN TABLE command.

IMPORT FOREIGN SCHEMA options

mysql_fdw supports IMPORT FOREIGN SCHEMA and accepts the following custom options:

TRUNCATE support

mysql_fdw implements the foreign data wrapper TRUNCATE API, available from PostgreSQL 14. MySQL does provide a TRUNCATE command, see https://dev.mysql.com/doc/refman/8.4/en/truncate-table.html.

Following restrictions apply:

Functions

As well as the standard mysql_fdw_handler() and mysql_fdw_validator() functions, mysql_fdw provides the following user-callable utility functions:

Generated columns

Note that while mysql_fdw will insert or update the generated column value in MySQL, there is nothing to stop the value being modified within MySQL, and hence no guarantee that in subsequent SELECT operations the column will still contain the expected generated value. This limitation also applies to postgres_fdw.

For more details on generated columns see:

Examples

Install the extension:

Once for a database you need, as PostgreSQL superuser.

    -- load extension first time after install
    CREATE EXTENSION mysql_fdw;

Create a foreign server with appropriate configuration:

Once for a foreign datasource you need, as PostgreSQL superuser.

    -- create server object
    CREATE SERVER mysql_server
    FOREIGN DATA WRAPPER mysql_fdw
    OPTIONS (host '127.0.0.1', port '3306');

Grant usage on foreign server to normal user in PostgreSQL:

Once for a normal user (non-superuser) in PostgreSQL, as PostgreSQL superuser. It is a good idea to use a superuser only where really necessary, so let's allow a normal user to use the foreign server (this is not required for the example to work, but it's security recommendation).

    GRANT USAGE ON FOREIGN SERVER mysql_server TO pguser;

Where pguser is a sample user for works with foreign server (and foreign tables).

User mapping

Create an appropriate user mapping:

    -- create user mapping
    CREATE USER MAPPING FOR pguser
    SERVER mysql_server
    OPTIONS (username 'foo', password 'bar');

Where pguser is a sample user for works with foreign server (and foreign tables).

Create foreign table

All CREATE FOREIGN TABLE SQL commands can be executed as a normal PostgreSQL user if there were correct GRANT USAGE ON FOREIGN SERVER. No need PostgreSQL supersuer for security reasons but also works with PostgreSQL supersuer.

Please specify table_name option if MySQL table name is different from foreign table name.

    -- create foreign table
    CREATE FOREIGN TABLE warehouse (
      warehouse_id int,
      warehouse_name text,
      warehouse_created timestamp
    )
    SERVER mysql_server
    OPTIONS (dbname 'db', table_name 'warehouse');

Some other operations with foreign table data

-- insert new rows in table
INSERT INTO warehouse values (1, 'UPS', current_date);
INSERT INTO warehouse values (2, 'TV', current_date);
INSERT INTO warehouse values (3, 'Table', current_date);

-- select from table
SELECT * FROM warehouse ORDER BY 1;

warehouse_id | warehouse_name | warehouse_created
-------------+----------------+-------------------
           1 | UPS            | 10-JUL-20 00:00:00
           2 | TV             | 10-JUL-20 00:00:00
           3 | Table          | 10-JUL-20 00:00:00

-- delete row from table
DELETE FROM warehouse where warehouse_id = 3;

-- update a row of table
UPDATE warehouse set warehouse_name = 'UPS_NEW' where warehouse_id = 1;

-- explain a table with verbose option
EXPLAIN VERBOSE SELECT warehouse_id, warehouse_name FROM warehouse WHERE warehouse_name LIKE 'TV' limit 1;

                                   QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Limit  (cost=10.00..11.00 rows=1 width=36)
    Output: warehouse_id, warehouse_name
    ->  Foreign Scan on public.warehouse  (cost=10.00..1010.00 rows=1000 width=36)
        Output: warehouse_id, warehouse_name
        Local server startup cost: 10
        Remote query: SELECT `warehouse_id`, `warehouse_name` FROM `db`.`warehouse` WHERE ((`warehouse_name` LIKE BINARY 'TV'))

Import a MySQL database as schema to PostgreSQL:

    IMPORT FOREIGN SCHEMA someschema
    FROM SERVER mysql_server
    INTO public;

Limitations

Yet not described.

For more details, please refer to mysql_fdw documentation.

Contributing

If you experience any bug and have a fix for that, or have a new idea, create a ticket on github page. Before creating a pull request please read the contributing guidelines.

Support

This project will be modified to maintain compatibility with new PostgreSQL and EDB Postgres Advanced Server releases.

If you require commercial support, please contact the EnterpriseDB sales team, or check whether your existing PostgreSQL support provider can also support mysql_fdw.

Useful links

Source code

Reference FDW implementation, postgres_fdw

General FDW Documentation

Other FDWs

License

Copyright (c) 2011-2024, EnterpriseDB Corporation.

Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies.

See the LICENSE file for full details.