PostgreSQL 技术内幕(十七):FDW 实现原理与源码解析
对于一定规模的系统而言,数据仓库往往需要访问外部数据来完成分析和计算。外部数据包装器(Foreign Data Wrapper, 简称 FDW)是 PostgreSQL 提供的访问外部数据源机制。用户可以使用简单的 SQL 语句访问和操作外部数据源,就像操作本地表一样。在上次直播中,我们深入探讨了 PostgreSQL FDW 的基本概念、详细使用方法、实现原理以及源码实现。以下是根据直播内容整理成稿。
01 FDW 使用详解
FDW 是 PostgreSQL 中的一项关键特性,它赋予数据库用户直接通过 SQL 语句访问存储于外部数据源的能力。FDW 遵循 SQL/MED 标准设计,使 PostgreSQL 能够无缝对接多种异构数据库系统以及非数据库类数据源。
FDW 可以用于以下场景:
1. 跨数据库查询:在 PostgreSQL 数据库中,我们可以通过 FDW 直接请求和查询其他 PostgreSQL 实例,或是其他数据库如 MySQL、Oracle、DB2、SQL Server 等。
2. 数据整合:当我们需要从不同数据源整合数据时,例如 REST API、文件系统、NoSQL 数据库以及流式系统等,FDW 能够帮助我们轻松实现这种跨来源的数据整合。
3. 数据迁移:利用 FDW,我们可以高效地将数据从旧系统迁移到新的 PostgreSQL 数据库中。
4. 实时数据访问:通过 FDW,我们能够访问外部实时更新的数据源。
PostgreSQL 支持非常多常见的 FDW,能够直接访问多种类型的外部数据源。例如,可以连接并查询远程的 PostgreSQL,或者主流的 SQL 数据库如 Oracle、MySQL、DB2 以及 SQL Server。同时,PostgreSQL FDW 也具备灵活的接口,支持用户自定义外部访问方式。
表 1。常见的 FDW—SQL Database
此外,对于 NoSQL 数据库,如 HBase、Cassandra、ClickHouse,以及实时数据库如 InfluxDB、消息队列如 Kafka、文档型数据库如 MongoDB 等等都能通过 FDW 实现数据访问。
表 2。常见的 FDW—NoSQL Database
常见的文本格式数据,如 CSV、JSON、Parquet 和 XML,也可以通过 FDW 轻松访问。大数据组件如 Elasticsearch、BigQuery,以及 Hadoop 生态系统中的 HDFS 和 Hive 等等都可以通过 FDW 实现无缝集成。
表 3。常见的 FDW—File Wrapper
表 4。常见的 FDW—Big Data
FDW 机制由四个核心组件构成:
1. Foreign Data Wrapper:特定于各数据源的库,定义了如何建立与外部数据源的连接、执行查询及处理其他操作。例如,postgres_fdw
用于连接其他 PostgreSQL 服务器,mysql_fdw
则专门连接 MySQL 数据库。
2. Foreign Server:在本地 PostgreSQL 中定义一个外部服务器对象,对应实际的远程或非本地数据存储实例。
3. User Mapping:为每个外部服务器设置用户映射,明确哪些本地用户有权访问,并提供相应的认证信息,如用户名和密码。
4. Foreign Table:在本地数据库创建表结构,作为外部数据源中表的映射。对这些外部表发起的 SQL 查询将被转换并传递给相应的 FDW,在外部数据源上执行。
接下来,我们以常见的 postgres_fdw
为例,来简要探讨一下 FDW 的基本使用方法。
步骤一:创建插件
步骤二:创建 Foreign Server
步骤三:创建 User Mapping
步骤四:创建外部表
02 FDW 实现原理
在 PostgreSQL 的内核代码中,FDW 访问外部数据源的操作接口主要通过 FdwRoutine 这一结构体进行定义。任何接入外部数据源的插件都可以根据自身需要去实现这些接口。
图 1.FdwRoutine 定义了外部数据操作的接口
接口函数大致分为多个类别,包括但不限于扫描、修改、分析外部表等等。例如,扫描外部表相关接口定义了如何扫描外部表,常见的操作包括开始扫描( BeginForeignScan
,主要进行准备工作)、执行扫描(IterateForeignScan,从扫描中获取数据)、重新扫描(RescanForeignScan
)以及结束扫描(EndForeignScan)等。
图 2。扫描外部表相关接口
此外,还有用于修改数据的外部表接口,支持对数据进行 insert、delete、update 等操作,以及 explain 和 analyze 等外部表接口。
insert/delete/update 外部表接口
explain/analyze 外部表接口
注:需要明确的是,当实现一个访问外部数据源的 FDW 时,并不需要实现以上提到所有的外部访问数据接口。开发者只需根据实际需求实现对应的接口即可。例如,如果只访问查询某个 Web 数据源而不进行修改或删除操作,那么就不需要实现关于删改和更新的操作接口,只需实现 SCAN 扫描相关的接口即可。
如下图,这是一个 FDW 插件实现 FdwRoutine 的示例,这里仅实现了一些基础的扫描操作接口(如BeginForeignScan
、IterateForeignScan
等),以及用于性能分析的AnalyzeForeignTable
接口。
插件实现 FdwRoutine
在 PostgreSQL 的执行过程中,这些接口函数会在 planner 或 executor 阶段被调用。尤其是当 executor 需要依赖外部服务插件访问数据时,它会通过插件提供的数据访问接口来获取数据。这使得 FDW 能够与 PostgreSQL 的 Parser、Planner 以及 Rewriter 等组件能够无缝协作。
在需要访问外部数据源时,我们只需定义好相应的数据访问接口,就能直接获取数据,并按照 PostgreSQL 的标准流程进行后续处理。在执行过程中,执行器会分解为几个阶段进行:
1、首先进入 init 阶段,核心任务是执行外部表扫描ExecInitForeignScan
。在这个阶段,主要是定义了一些外部扫描的接口,并调用 FdwRoutine 中用户自定义的接口,从而进行扫描前的准备。
执行 scan 前的准备
2、紧接着是执行查询阶段,此时会调用ExecuteForeignScan
方法。在这个方法中,我们主要需指定ForeignNext
来获取下一组数据,并定义 ForeignRecheck
来检验数据元组的可见性。
执行查询阶段
3、最后进入结束查询阶段,即执行 EndForeignScan
,该阶段主要负责资源清理工作。若系统检测到存在 FDWRoutine,就会利用用户自定义的 EndForeignScan
函数来释放资源。
结束查询阶段
以上就是 FDW 整体的实现流程。接下来,为了更深入地了解 FDW 的工作机制,我们将深入探讨 FDW 的源码。
03 FDW 源码解析
FDW 支持的数据类型众多,但在此我们以常见的Postgres_fdw
为例,剖析其源码实现,同样可帮助理解其他 FDW 的源码逻辑。
FdwRoutine 定义
首先,我们需要定义 FdwRoutine。前文提到了 FdwRoutine 主要负责定义外部数据扫描的接口,接口需要自定义实现外部扫描的方法。
FdwRoutine 定义
访问外部数据源
定义好 FdwRoutine 之后,开始访问并扫描外部数据源。在Postgres_fdw
中,流程也就是进入BeginForeign Scan
阶段。这一阶段主要是获取我们先前定义的外部表实例和用户信息,然后初始化并获取一个连接到远端数据源。
postgresBeginForeignScan
执行查询阶段
获取连接后,执行查询,即进行 IterateForeignScan
阶段。这个过程的逻辑是创建一个游标迭代器(cursor),并从 cursor 中持续获取数据。
postgresIterateForeignScan
当全部数据迭代或扫描完成后,我们会释放连接并关闭 cursor 等资源,通过自定义的EndForeignScan
阶段完成。
postgresEndForeignScan
insert 操作
对于 insert 操作,例如,在本地 PostgreSQL 数据库中修改 Web 数据源,增加一条数据,需要访问插入 Web 数据的接口。此操作先进入BeginForeignInsert
阶段,任务是构造 SQL 语句,通过预处理语句进行初始化,做好插入准备。
postgresBeginForeignInsert
之后,进入ExecuteForeignInsert
阶段,执行数据插入,主要通过预处理语句传递参数,然后发送 SQL 到远端执行。
postgresExecForeignInsert
最后,EndForeignInsert
阶段负责收尾和资源清理。
postgresEndForeignInsert
更新/删除操作
更新和删除操作的逻辑与插入类似。首先进入BeginDirectModify
阶段,进行数据修改前的准备,如构建查询语句、获取连接等。随后执行修改操作,主要通过发送参数和查询到远端来执行。
postgresBeginDirectModify
postgresIterateDirectModify
本次分享,我们为大家讲解了 FDW 基本概念、使用场景、实现原理,以及源码解析,文章篇幅有限,更多技术细节讲解欢迎大家访问 B 站 https://www.bilibili.com/video/BV1pf421X7pk/?share_source=copy_web&vd_source=9f256c264f70725955bae178113d4bee,观看视频回放,希望能与朋友们一起更好地理解和用好 FDW。
评论