Feast PostgreSQL 数据源实战:PostgreSQLSource 配置、类型映射与 Point-in-Time Join 实现解析 Feast PostgreSQL 数据源实战PostgreSQLSource 配置、类型映射与 Point-in-Time Join 实现解析【免费下载链接】feastThe Open Source Feature Store for AI/ML项目地址: https://gitcode.com/GitHub_Trending/fe/feastFeast 中的 PostgreSQL 批量数据源PostgreSQLSource允许你直接把 Postgres 表或视图作为特征数据的来源既可以通过表名引用也可以通过任意 SQL 查询定义。本篇围绕该数据源的官方参考文档展开补全其全部构造参数、仓库级连接配置feature_store.yaml与PostgreSQLConfig、类型支持矩阵并结合源码解析 Feast 如何基于该数据源生成 Point-in-Time Join SQL、执行特征检索与类型映射帮助你在 Feast 仓库中实际搭建以 PostgreSQL 为后端离线存储的批量特征管道。一、PostgreSQL 数据源是什么PostgreSQL 数据源在 Feast 中由PostgreSQLSource类实现位于 postgres_source.py。它表示的是一张PostgreSQL 表或视图有两种指定方式表引用table reference通过table参数直接给出表名SQL 查询SQL query通过query参数给出任意 SELECT 查询适合从多表 JOIN、过滤或聚合后的结果上取特征。官方参考文档位于 postgres.md其中给出了最简的查询式定义示例from feast.infra.offline_stores.contrib.postgres_offline_store.postgres_source import ( PostgreSQLSource, ) driver_stats_source PostgreSQLSource( namefeast_driver_hourly_stats, querySELECT * FROM feast_driver_hourly_stats, timestamp_fieldevent_timestamp, created_timestamp_columncreated, )该示例与仓库中 Postgres 模板 feature repo 的完整定义feature_definitions.py一致模板中进一步将该数据源绑定到一个带ttltimedelta(days1)、onlineTrue的FeatureViewdriver_hourly_stats并组合进FeatureService展示了从数据源到特征视图、再到在线服务的完整链路。稳定性说明官方原文警示参考文档明确声明 The PostgreSQL data source does not achieve full test coverage. Please do not assume complete stability.PostgreSQL 数据源未达到完整测试覆盖请勿假设其完全稳定。此外数据源总览 的功能矩阵也将PostgreSQLSource归类为社区贡献contrib实现与FileSource、BigQuerySource、SnowflakeSource、RedshiftSource等核心实现并列但稳定性不作保证。生产使用前建议在 CI 中加入自己的回归验证。二、PostgreSQLSource 完整参数说明PostgreSQLSource的构造签名见 postgres_source.py#L28-L40完整参数如下参数类型 / 默认值说明nameOptional[str]默认None数据源名称项目内需唯一。若未提供name但提供了table则以表名作为默认名称name与table同时为空会抛出DataSourceNoNameExceptionqueryOptional[str]默认None用于取数的 SQL 查询语句与table二选一的取数方式tableOptional[str]默认None表名与query二选一的取数方式timestamp_fieldOptional[str]默认事件时间戳字段用于 Point-in-Time Join 中选取事件时间点的特征值created_timestamp_columnOptional[str]默认行创建时间戳列用于对同一事件时间点的重复行去重保留创建时间最新的一行field_mappingOptional[Dict[str, str]]数据源列名到特征名的映射仅作用于特征列不作用于实体列或时间戳列descriptionOptional[str]人类可读的描述tagsOptional[Dict[str, str]]任意键值对元数据ownerOptional[str]数据源负责人通常是主要维护者的邮箱connection_refOptional[ConnectionRef]为该数据源单独指定外部凭据引用见下文类上还实现了两个值得注意的方法get_table_column_names_and_types(config)通过SELECT * FROM {表/查询} AS sub LIMIT 0执行零行查询利用游标的description拿到列名与 Oid 类型码再经pg_type_code_to_pg_type映射为 PostgreSQL 类型名postgres_source.py#L137-L148__eq__/__hash__除基类字段外还比较query、timestamp_field、created_timestamp_column、field_mapping保证注册表中相同数据源对象可正确判等。三、表引用与 SQL 查询子查询别名问题Postgres 要求FROM子句中的所有子查询必须带别名这是 query 式数据源最容易踩的坑。PostgreSQLSource为此提供了两个方法postgres_source.py#L150-L188def get_table_query_string(self) - str: 表式来源返回表名查询式来源返回带括号的查询 (query) def get_table_query_string_with_alias(self, alias: str subquery) - str: 表式来源原样返回表名查询式来源返回 (query) AS aliastable式来源两者行为一致直接返回表名query式来源前者返回(SELECT ...)后者返回(SELECT ...) AS subquery。从源码结构看Feast 内部取全量/最新数据pull_all_from_table_or_query与计算监控指标时会显式追加别名例如FROM {from_expression} AS paftoq_aliaspostgres.py#L294-L324、FROM {from_expression} AS max_ts_aliaspostgres.py#L400-L405避免手写 SQL 时忘记别名导致syntax error。如果你基于该数据源自建查询建议统一使用get_table_query_string_with_alias()。四、仓库级配置feature_store.yaml 与连接参数数据源本身不携带连接信息连接参数来自feature_store.yaml的offline_store配置。仓库中的 Postgres 模板给出了标准写法feature_store.yamlproject: my_project provider: local registry: registry_type: sql path: postgresql://DB_USERNAME:DB_PASSWORDDB_HOST:DB_PORT/DB_NAME?sslmodeDB_SSLMODE cache_ttl_seconds: 60 sqlalchemy_config_kwargs: echo: false pool_pre_ping: true online_store: type: postgres host: DB_HOST port: DB_PORT database: DB_NAME db_schema: DB_SCHEMA user: DB_USERNAME password: DB_PASSWORD sslmode: DB_SSLMODE offline_store: type: postgres host: DB_HOST port: DB_PORT database: DB_NAME db_schema: DB_SCHEMA user: DB_USERNAME password: DB_PASSWORD sslmode: DB_SSLMODE entity_key_serialization_version: 3offline_store段由 postgres_config.py 中的PostgreSQLConfig解析完整字段及默认值如下字段默认值说明host必填数据库主机port5432端口database必填数据库名db_schemapublic目标 schema。连接时会注入options-c search_path{schema},public因此 schema 内的表无需带前缀即可访问见 connection_utils.py#L69-L80user/password必填认证信息sslmoderequireSSL 模式默认强制 SSLsslkey_path/sslcert_path/sslrootcert_pathNone客户端证书与 CA 证书路径min_conn/max_conn1/10连接池的最小/最大连接数conn_typesingleton连接模式singleton单连接或pool连接池keepalives_idleNoneTCP keepalive 空闲秒数底层通过psycopgv3建连_get_conn()使用make_conninfo拼装conninfo字符串并支持同步/异步连接与ConnectionPool连接池connection_utils.py#L15-L54。PostgreSQLOfflineStoreConfig在PostgreSQLConfig之上还增加了一个离线存储专属选项postgres.py#L72-L74class PostgreSQLOfflineStoreConfig(PostgreSQLConfig): type: Literal[postgres] postgres entity_select_mode: EntitySelectMode EntitySelectMode.temp_tableentity_select_mode控制历史特征检索时实体 DataFrame / 实体 SQL 的处理方式temp_table默认把实体 DataFrame 上传为 Postgres 临时表或把实体 SQL 物化为表查询完成后自动DROP TABLE IF EXISTSembed_query仅当实体输入是 SQL 字符串时生效直接以 CTEWITH entity_query AS (...)形式内联进检索 SQL省去建表开销。凭据隔离ConnectionRef参考文档提到的完整配置选项中包含connection_ref。根据数据源总览ConnectionRef允许每个数据源声明自己的外部凭据引用Kubernetes Secrets、HashiCorp Vault、环境变量等用于多租户部署与凭据隔离有connection_ref时凭据在运行时从外部提供者解析并覆盖全局 offline store 配置没有时回落到feature_store.yaml。PostgreSQLSource构造函数与from_proto反序列化均接受connection_refpostgres_source.py#L39。五、类型支持参考文档声明 PostgreSQL 数据源支持全部 8 种原始类型及其对应数组类型。结合 overview.md 的功能矩阵Postgres 列的支持情况为bytes、string、int32、int64、float32、float64、bool、timestamp均为 yes数组类型为 yes额外还支持Mapjson/jsonb、Json与Struct。映射关系定义在 type_map.py 中pg_type_to_feast_value_typetype_map.py#L2042把 Postgres 类型名映射为 FeastValueType例如integer/smallint→INT32、bigint→INT64、real→FLOAT、double precision→DOUBLE、timestamp with time zone/timestamp without time zone/date→UNIX_TIMESTAMP、json/jsonb→MAP、uuid→UUID以及各类[]数组类型到*_LIST的映射pg_type_code_to_pg_typetype_map.py#L2140把游标返回的 Oid 类型码如 23→integer、1184→timestamp with time zone、3802→jsonb还原为类型名。从源码结构看对未知类型码它不抛异常而是返回unknownFeast 会跳过问题列并打印警告——这一点在含自定义类型的库中要留意pg_type_code_to_arrow则用于检索结果直接构建 PyArrow schemafeast_value_type_to_pa保证 Arrow 列类型与 Postgres 类型一致。六、检索实现Point-in-Time Join 是如何生成的PostgreSQLOfflineStorepostgres.py声明supports_filter_by_created_timestamp True即该数据源支持按created_timestamp_column过滤与数据源定义中的created_timestamp_column参数呼应。核心检索路径有两条1. 单视图取数pull_latest / pull_allpull_latest_from_table_or_querypostgres.py#L80-L150在时间窗BETWEEN {start_date}::timestamptz AND {end_date}::timestamptz内优先用 Postgres 特有的SELECT DISTINCT ON (join_keys)按实体取每实体最新一行若指定了created_timestamp_column排序键追加created DESC实现重复行去重pull_all_from_table_or_querypostgres.py#L281-L331默认物化路径按get_timestamp_filter_sql生成时间过滤后整表拉取当feature_name_columns为空BatchFeatureView 的 python/pandas/ray 转换信号时退化为SELECT *避免只选 join key 时间戳导致 UDF 缺少输入特征。2. 多视图历史特征get_historical_featuresget_historical_featurespostgres.py#L152-L279的调用链为推断实体时间戳列并计算实体时间戳范围非实体无 entity_df检索时自动合成仅含end_date的合成实体行依据entity_select_mode决定temp_table物化或embed_queryCTE用 Jinja2 渲染MULTIPLE_FEATURE_VIEW_POINT_IN_TIME_JOIN模板postgres.py#L809 起。模板注释明确说明其改编自 Feast Redshift 离线存储实现。该模板生成的 SQL 结构是典型的 Feast 时间旅行连接entity_dataframeCTE对每个特征视图计算entity_row_unique_id实体列与时间戳拼接的确定性标识{{view}}__subquery先用timestamp_field MAX(entity_timestamp)与 TTL 下界entity_timestamp - ttl * interval 1 second粗筛{{view}}__baseINNER JOIN 实体逐行保证event_timestamp entity_timestamp且满足 TTL若开启filter_by_created_timestamp还附加created_timestamp entity_timestamp条件{{view}}__dedup/{{view}}__latest基于created_timestamp做MAX去重后用ROW_NUMBER() OVER (PARTITION BY entity_row_unique_id ORDER BY event_timestamp DESC, created_timestamp DESC)取每实体每时间点唯一最新行最终按entity_row_unique_id把各视图结果 LEFT JOIN 回实体表得到与实体行对齐的训练数据。3. 结果物化PostgreSQLRetrievalJob所有检索最终包装为PostgreSQLRetrievalJobpostgres.py#L603-L684_to_arrow_internal以read_onlyTrue执行查询从游标description推断 Arrow 字段类型按列转置后构建pa.Table再转 pandas查询零列时会抛出ZeroColumnQueryResultpersist()借助SavedDatasetPostgreSQLStorage把结果写回 Postgres 表df_to_postgres_table会按 Arrow 类型推导CREATE TABLE语句并executemany插入。此外该离线存储还内置了 SQL 下推的监控指标能力compute_monitoring_metrics用单条聚合 SQL 批量计算数值特征的mean/stddev/min/max/p50~p99PERCENTILE_CONT分位数 width_bucket直方图与分类特征的 Top-N 分布并通过INSERT ... ON CONFLICT DO UPDATE把指标 upsert 到ensure_monitoring_tables创建的原生监控表postgres.py#L1108-L1300。七、实战建议与小结优先用table指向物化好的视图/表query 式来源会以内联子查询进入所有生成的 SQL物化、检索、监控大查询应确保自身索引完备timestamp_field用timestamptz检索 SQL 统一以::timestamptz强转时间边界naive timestamp 与 timestamptz 混用容易引入时区偏差多实体视图去重依赖created_timestamp_column若源表存在同一事件时间点的重复写入务必设置该列以获得确定性去重关注稳定性声明官方文档与功能矩阵均提示该 contrib 数据源无完整测试覆盖单元测试位于 test_postgres.py关键链路建议纳入自有回归schema 与 SSLdb_schema通过search_path生效、sslmode默认require跨 schema 或内网自签证书环境需显式配置sslrootcert_path等字段。综上Feast 的 PostgreSQL 数据源以PostgreSQLSource表或 SQL 查询为入口通过feature_store.yaml的offline_store段完成连接配置类型系统经 Oid 类型码—Postgres 类型名—Feast ValueType 两级映射对齐检索层利用DISTINCT ON与ROW_NUMBER窗口函数在 Postgres 内完成 Point-in-Time Join并以 Arrow 管道物化结果。理解上述参数与 SQL 生成逻辑后即可在 Feast 中把任意可查询的 Postgres 表/视图接入批量特征管道。【免费下载链接】feastThe Open Source Feature Store for AI/ML项目地址: https://gitcode.com/GitHub_Trending/fe/feast创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考