如果你对 DuckDB 的印象还停留在本地分析、CSV 文件查询、Parquet 处理神器、Pandas 替代工具等,那么是时候了解一下这款官方 MySQL 扩展插件了。

DuckDB 提供的 MySQL 扩展插件可以让它把 MySQL 服务器当成一个可挂载的外部数据库,连接之后可以像访问本地 DuckDB 数据表一样访问 MySQL 中的数据,同时还支持写回 MySQL。
应用场景
- 实时数据分析:传统架构需要将业务系统数据库(例如MySQL)通过 ETL 同步到数据仓库中进行数据分析,DuckDB 则可以通过插件直接读取 MySQL 数据进行实时分析。
- 轻量级 ETL 数据管道:许多企业需要将数据库同步到数据湖中,DuckDB 通过一个命令就可以完成从 MySQL 到 Parquet 数据湖转换。
- 数据库迁移:DuckDB 可以作为中间组件实现 MySQL 到 MySQL 的数据迁移,以及 MySQL 到 PostgreSQL 等的数据迁移。
- 轻量级数据平台:很多中小公司没有数仓团队,无法支持 ClickHouse 这种大型平台;使用 MySQL + DuckDB + Metabase 这种轻量级报表分析系统维护成本极低。
安装加载
使用 INSTALL 语句安装 MySQL 插件的命令如下:
sql
INSTALL mysql
首次使用时,系统会自动加载插件,或者也可以手动加载:
sql
LOAD mysql;
连接 MySQL
DuckDB 提供了 ATTACH 命令,用于加载外部数据库连接。例如:
sql
ATTACH 'host=localhost port=3306 database=dbname user=root password=xxxxxx' AS mysqldb (TYPE mysql);
USE mysqldb;
其中的连接参数需要替换为真实数据,这样 MySQL 数据库就被挂载到 DuckDB 中了。
除了以上参数之外,还可以指定 SSL 安全连接以及连接池配置。
为了不在 SQL 中暴露密码,推荐使用 DuckDB 密钥(Secret)管理器。例如:
sql
-- 创建密钥
CREATE SECRET (
TYPE mysql,
HOST '127.0.0.1',
PORT 3306,
DATABASE dbname,
USER 'root',
PASSWORD 'XXXXXX'
);
-- 挂载数据库
ATTACH '' AS mysqldb (TYPE mysql);
DuckDB 还支持密钥的持久化存储,同时也可以通过命名密钥管理多个 MySQL 实例。
读取 MySQL
连接到 MySQL 实例之后,可以像普通 DuckDB 数据表一样查询 MySQL 中的数据。例如:
sql
SELECT customer_id, first_name,last_name
FROM mysqldb.sakila.customer LIMIT 3;
┌─────────────┬────────────┬───────────┐
│ customer_id │ first_name │ last_name │
│ uint16 │ varchar │ varchar │
├─────────────┼────────────┼───────────┤
│ 1 │ MARY │ SMITH │
│ 2 │ PATRICIA │ JOHNSON │
│ 3 │ LINDA │ WILLIAMS │
└─────────────┴────────────┴───────────┘
如果想要将 MySQL 数据复制到 DuckDB 表中,同样非常简单:
sql
CREATE TABLE local_customer AS
FROM mysqldb.sakila.customer;
SELECT COUNT(*) FROM local_customer;
┌──────────────┐
│ count_star() │
│ int64 │
├──────────────┤
│ 599 │
└──────────────┘
写入 MySQL
DuckDB 不仅可以通过插件读取 MySQL 中的数据,同样也可以将数据写入 MySQL 数据库。例如:
sql
-- 远程创建 MYSQL 数据表
CREATE TABLE mysqldb.t1(id INTEGER, name VARCHAR);
-- 写入数据
INSERT INTO mysqldb.t1 VALUES (42, 'DuckDB');
SELECT * FROM mysqldb.t1;
┌───────┬─────────┐
│ id │ name │
│ int32 │ varchar │
├───────┼─────────┤
│ 42 │ DuckDB │
└───────┴─────────┘
我们不仅可以写入 MySQL 数据,还可以执行 DDL 语句以及其他数据修改操作;如果担心误操作可能对 MySQL 数据库的影响,可以在 ATTACH 命令中使用只读参数。例如:
sql
ATTACH '' AS mysqldb (TYPE mysql, READ_ONLY);
此时,我们只能执行数据查询,不能执行其他修改操作。
MySQL 插件还支持事务处理语句,例如 BEGIN、COMMIT、ROLLBACK。
数据交换
除了实时查询 MySQL 数据或者将其复制到 DuckDB 数据表中,我们还可以进一步将 DuckDB 作为轻量级 ETL 引擎,实现数据管道功能。例如:
sql
-- MySQL 数据导出 Parquet 文件
COPY mysqldb.orders
TO 'orders.parquet';
-- Parquet 文件导入 MySQL
COPY mysqldb.orders
FROM 'orders.parquet';
原生 MySQL 语句
MySQL 插件还提供了两个函数,用于在远程数据库中执行 SQL 命令,支持 MySQL 专有语法。
mysql_query 表函数用于执行一个查询语句并返回结果,例如:
sql
-- 查询 MySQL 版本
SELECT * FROM mysql_query(
'mysqldb',
'SELECT version();'
);
┌───────────┐
│ version() │
│ varchar │
├───────────┤
│ 8.4.8 │
└───────────┘
mysql_execute 函数用于执行任意 MySQL 命令,包括 DDL 以及 DML。例如:
sql
-- 创建远程 MySQL 数据表
CALL mysql_execute('mysqldb', 'CREATE TABLE my_table (i INTEGER)');
总结
MySQL 扩展插件实现了 DuckDB 远程访问 MySQL 数据库的功能,使得 DuckDB 正在从一个嵌入式分析型数据库逐渐进化成一个联邦数据查询平台。
参考文档: