跳转至

第 10 章 Data Plane:数据执行环境

本章学习目标 - 理解 Data Plane 的容器编排(PG Supernode / pg_mooncake / MinIO)与各组件职责 - 掌握 semlayer schema 与列存镜像的设计原理 - 理解双数据面后端(Redshift / pg_mooncake)切换机制与 SQL 方言适配 - 了解 H&M 测试数据集及其加载流程 - 认清当前数据面设计的工程权衡与改进方向

前置知识第 2 章 整体架构第 5 章 RAG 检索(PG Supernode) 关联代码data-plane/(docker-compose、sql、scripts)


10.1 背景与动机

Data Plane 是 TTD 的执行态——语义治理资产发布到这里供 Agent 检索(第 9 章),用户的 SQL 也在这里执行。它有两个职责:

  1. 承载语义层:R/V/G/D 四引擎的数据存储(PG Supernode)
  2. 承载业务数据:用户查询的实际数据(Redshift 生产 / pg_mooncake 开发)

与 Semantic Plane(Git YAML 治理态)分离,是 ADR-1 的核心决策。这个分离让治理有版本控制、可审查,执行有低延迟、高吞吐。


10.2 设计原理

10.2.1 容器编排

C4Deployment
title Data Plane 容器编排 — Deployment Diagram

    Deployment_Node(docker_host, "Data Plane Docker 宿主", "Docker Engine 27+ · docker-compose", "data-plane/docker-compose.yml 定义的全部服务") {
        Container(pg_container, "postgres (PG Supernode)", "age-pgvector:local · PG 18 · :5435", "PG Supernode:pgvector+AGE 扩展,承载 semlayer.*、ttd_governance AGE 图、检查点、会话、auth 表")
        Container(mooncake_container, "pg-mooncake (列存)", "mooncake-labs · :5436", "本地 Redshift 替代:gold_hm.* 列存镜像,OLAP 聚合加速")
        Container(minio_container, "minio (S3)", "minio/minio · :9000/:9001", "语义资产 S3 兼容存储,3 桶")
        Container(minio_init, "minio-init", "minio/mc · 一次性", "启动时创建 S3 桶和策略")
        Container(automq_container, "automq (消息队列)", "AutoMQ · Kafka 协议 · 可选", "可观测事件总线,仅 debug 时启动")
    }

    System_Ext(s3_publish, "S3 发布桶", "AWS S3 / MinIO", "接收 publish_semantic_plane.py 发布的资产")

    Rel(pg_container, minio_container, "语义资产发布到 S3", "S3 API")
    Rel(minio_init, minio_container, "初始化桶和策略", "mc admin")
    Rel(mooncake_container, pg_container, "列存查询依赖语义层", "psycopg")
    Rel(automq_container, pg_container, "消费可观测事件", "Kafka 协议")
    Rel(pg_container, s3_publish, "发布语义资产到 S3", "S3 API")

    UpdateElementStyle(pg_container, $fontColor="#202124", $bgColor="#e0f2f1", $borderColor="#0d7377")
    UpdateElementStyle(mooncake_container, $fontColor="#202124", $bgColor="#e0f2f1", $borderColor="#0d7377")
    UpdateElementStyle(minio_container, $fontColor="#202124", $bgColor="#e0f2f1", $borderColor="#0d7377")
    UpdateElementStyle(minio_init, $fontColor="#202124", $bgColor="#e8f0fe", $borderColor="#1a73e8")
    UpdateElementStyle(automq_container, $fontColor="#202124", $bgColor="#e0f2f1", $borderColor="#0d7377")
    UpdateElementStyle(s3_publish, $fontColor="#5f6368", $bgColor="#f8f9fa", $borderColor="#dadce0")

    UpdateRelStyle(pg_container, minio_container, $textColor="#0d7377", $lineColor="#0d7377")

    UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="2")
容器 镜像 端口 用途 设计理由
postgres age-pgvector:local(Apache AGE PG18 + pgvector 源码编译) 5435 PG Supernode(R/V/G + 会话 + 检查点) 一体化:R/V/G 共享一个 PG 实例,事务一致、运维简单
pg-mooncake mooncake-labs 列存 5436 本地 Redshift 替代(列存查询) 列存适合 OLAP 聚合,本地替代 Redshift 降低开发成本
minio S3 兼容 9000/9001 语义资产发布 + 对象存储 S3 兼容协议,与生产 S3 无缝切换
minio-init 桶初始化(talktodata/automq-data/automq-ops) 自动化初始化
automq Kafka 兼容 可观测事件总线(可选) 与生产 Kafka 协议兼容

10.2.2 PG Supernode

PG Supernode 将 R/V/G 三引擎(+ D)统一在同一 PostgreSQL 实例——这是 ADR-2 的"一体化"策略:

Schema/图 引擎 内容 说明
semlayer.* R 语义层关系表(17 张 + 8 张 embedding 表) 结构化精确查询
*_embedding V pgvector 向量表 语义相似度检索
ttd_governance G Apache AGE 属性图 关系推理
semlayer.dynamic_few_shot_cache D 动态 few-shot 在线学习
semlayer.sql_cache SQL 语义缓存 性能优化
ttd.* Backend ORM 表(会话/反馈/模型配置等) 应用数据
auth 表 Better Auth(user/session/jwks) 认证

10.2.3 列存镜像

gold_hm.* 列存表是 H&M 业务数据的列式存储镜像,由 pg_mooncake 提供:

  • 源表 _src(从 CSV 加载)+ mooncake.create_table() 创建列存镜像
  • 为什么用列存:OLAP 聚合查询(SUM/COUNT/GROUP BY)在列存上远快于行存——列存按列压缩、只读所需列、向量化执行。这正是 Redshift/Snowflake 等 OLAP 引擎的核心。

10.3 实现详解

10.3.1 schema 初始化

SQL 文件 内容
data-plane/sql/001_create_schema.sql semlayer schema + pgvector + AGE 初始化(17 表 + 8 embedding 表 + AGE 图 + SQL cache)
data-plane/sql/100_hm_create_schema.sql H&M gold 表 DDL

10.3.2 Schema 深潜

001_create_schema.sql 定义了语义层的完整关系结构。本节展示关键表的 DDL,让读者建立对"语义层物理形态"的具体认知。

扩展与图初始化

-- data-plane/sql/001_create_schema.sql
CREATE EXTENSION IF NOT EXISTS vector;   -- pgvector(Engine V)
CREATE EXTENSION IF NOT EXISTS age;       -- Apache AGE(Engine G)

-- 创建 AGE 属性图(Engine G 的数据载体)
LOAD 'age';
SET search_path = ag_catalog, "$user", public;
SELECT create_graph('ttd_governance')
WHERE NOT EXISTS (
    SELECT 1 FROM ag_catalog.ag_graph WHERE name = 'ttd_governance'
);

PG18 + Apache AGE 是非标准组合

Apache AGE 通常落后于最新 PostgreSQL 版本。TTD 使用 age-pgvector:local 镜像,是基于 PG18 源码编译 AGE + pgvector 的自定义构建。这意味着 AGE 版本升级需自行验证与 PG18 的兼容性,不能直接依赖 AGE 官方的 PG 版本支持矩阵。

metric_asset 表(Layer 1 指标资产)

-- data-plane/sql/001_create_schema.sql(第 110-129 行)
CREATE TABLE IF NOT EXISTS semlayer.metric_asset (
    metric_id               VARCHAR(128)  PRIMARY KEY,
    metric_name             VARCHAR(256)  NOT NULL,
    business_definition_zh  TEXT          NOT NULL,
    business_definition_en  TEXT          NOT NULL,
    sql_definition          TEXT          NOT NULL,
    default_grain           VARCHAR(128),
    allowed_dimensions      TEXT[],
    default_filters         TEXT[],
    owner                   VARCHAR(256)  NOT NULL,
    certification_status    VARCHAR(32)   NOT NULL DEFAULT 'draft',
    version                 VARCHAR(32)   NOT NULL DEFAULT '1.0.0',
    similar_metrics         JSONB,
    counter_examples        TEXT[],
    common_questions        TEXT[],
    created_at              TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
    updated_at              TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
    deleted_at              TIMESTAMPTZ,
    deleted_by              VARCHAR(256)
);

关键设计:similar_metrics(JSONB)记录易混淆指标及其差异,counter_examples(TEXT[])存储"这不是什么"的反例——两者在 Prompt 注入时帮助 LLM 避免指标混淆。certification_status 支撑 Reranker 对已认证资产的提权。

8 张 *_embedding 表与 HNSW 索引

所有嵌入表结构统一,以 table_asset_embedding 为例:

-- data-plane/sql/001_create_schema.sql(第 287-302 行)
CREATE TABLE IF NOT EXISTS semlayer.table_asset_embedding (
    table_id        VARCHAR(128)  PRIMARY KEY REFERENCES semlayer.table_asset(table_id),
    source_text     TEXT          NOT NULL,
    embedding       vector(1024)  NOT NULL,
    model_id        VARCHAR(128)  NOT NULL,
    model_version   VARCHAR(64)   NOT NULL,
    generated_at    TIMESTAMPTZ   NOT NULL DEFAULT NOW()
);

-- HNSW 索引(所有 8 张表统一参数)
ALTER TABLE semlayer.table_asset_embedding
    ALTER COLUMN embedding SET STORAGE PLAIN;

CREATE INDEX IF NOT EXISTS idx_table_emb_hnsw
    ON semlayer.table_asset_embedding
    USING hnsw (embedding vector_cosine_ops)
    WITH (m = 16, ef_construction = 128);
设计选择 理由
向量维度 vector(1024) text-embedding-v4 输出维度(注:ADR-7 记录 1536,与 schema 不一致,见 第 5 章
索引类型 HNSW 比 IVFFlat 召回率更高,查询延迟稳定
索引参数 m=16, ef_construction=128 平衡索引构建时间与召回质量
算子类 vector_cosine_ops 归一化向量的余弦相似度
存储 SET STORAGE PLAIN 避免 TOAST 压缩导致 HNSW 性能退化
模型版本追踪 model_id + model_version 支持嵌入迁移时按版本筛选重建

8 张表完整枚举见 第 5 章 5.3.4

10.3.3 数据加载

data-plane/scripts/load_hm_data.py 加载 H&M 数据到 pg_mooncake 列存表(COPY FROM STDIN)。

data-plane/scripts/publish_semantic_plane.pyttd-publish-sp)发布 semantic-plane YAML 到 S3。

10.3.4 双数据面切换

# .env 配置切换数据面
TTD_DATA_PLANE_BACKEND=redshift      # 生产
TTD_DATA_PLANE_BACKEND=pg_mooncake   # 开发
维度 生产 (Redshift) 开发 (pg_mooncake)
引擎 AWS Redshift Serverless pg_mooncake (PG + columnstore)
连接 redshift-connector psycopg
SQL 方言 Redshift SQL PostgreSQL
成本 按用量计费 本地免费
规模 PB 级 单机轻量

settings.sql_dialect 根据 data_plane_backend 自动返回方言,SQL Generator 在 prompt 中注入当前方言。这是"同一套代码适配多个执行后端"的抽象。

10.3.5 Backend 集成

Backend 通过环境变量切换数据面后端(详见 附录 B 环境变量)。数据面执行器抽象见 第 8 章

10.3.6 查询执行流

一条 SQL 从生成到结果回传的完整路径:

sequenceDiagram
    autonumber
    box rgb(232,240,254) AI Agent Pipeline
        participant SQLGen as SQL Generator
        participant Guard as Guardrails
        participant Exec as DataPlaneExecutor
    end
    box rgb(224,242,241) 数据执行环境
        participant Dialect as sqlglot 方言适配
        participant DP as 数据面(Redshift/pg_mooncake)
        participant Bridge as dataframe_bridge
    end

    SQLGen->>Guard: 生成的 SQL(PostgreSQL 方言)
    Guard->>Guard: 五层校验(语法/策略/列/术语/EXPLAIN)
    Guard->>Exec: 校验通过,SQL + max_rows + timeout
    Exec->>Dialect: 按 data_plane_backend 转译方言
    alt 生产(Redshift)
        Dialect->>Dialect: postgres → redshift(DISTKEY/SORTKEY 适配)
    else 开发(pg_mooncake)
        Dialect->>Dialect: 保持 PostgreSQL 方言
    end
    Dialect->>DP: 执行 SQL
    DP-->>Exec: columns + rows + row_count + execution_time_ms
    Exec-->>Bridge: 结果集
    Bridge->>Bridge: 转换为 pandas DataFrame(供分析/可视化)
    Bridge-->>SQLGen: DataFrame + 元数据

关键点:方言转译发生在执行前而非生成时——SQL Generator 始终以 PostgreSQL 方言生成(由 Prompt 注入),由 DataPlaneExecutor 在执行前用 sqlglot 转译为目标方言。这保证了生成逻辑的方言无关性。

10.3.7 pg_mooncake 内部

pg_mooncake 是 Mooncake Labs 提供的 PostgreSQL 列存扩展,TTD 用它在本地模拟 Redshift 的列存查询能力。

列存工作原理

特性 列存(pg_mooncake) 行存(标准 PG 堆表)
存储方式 按列组织,每列独立压缩 按行组织,整行连续存储
聚合查询 ——只读所需列,向量化执行,CPU 缓存友好 慢——需读取整行再提取列
点查询 慢——需跨列重组 ——整行连续读取
压缩率 高(同列数据类型一致)
写性能 较差(列存不适合高频写) ——追加写高效

OLAP 查询(SUM/COUNT/GROUP BY)在列存上远快于行存,这正是 Redshift/Snowflake 的核心。pg_mooncake 让本地 PG 也能获得类似加速。

列存镜像机制

-- 1. 源表(行存堆表,可写)
CREATE TABLE gold_hm.fact_transaction_src (...);

-- 2. 创建列存镜像(规范名,由 load_hm_data.py 调用)
CALL mooncake.create_table('gold_hm.fact_transaction', 'gold_hm.fact_transaction_src');

镜像使用规范名(无 _src 后缀),语义资产与生产 Redshift 共用此名。源表写入后,列存镜像自动同步(pg_mooncake 维护同步)。

pg_mooncake vs DuckDB vs Redshift

维度 pg_mooncake DuckDB Redshift
形态 PG 扩展 嵌入式独立引擎 云数据仓库
与 PG 一体化 是(共享实例)
列存 原生 原生
SQL 方言 PostgreSQL PostgreSQL 兼容 Redshift(有专有语法)
规模 单机 单机 PB 级
TTD 用途 开发数据面 未用 生产数据面

pg_mooncake ≠ Redshift

pg_mooncake 提供 PostgreSQL 方言的列存查询,但不等同于 Redshift——后者有 DISTKEY/SORTKEY 等专有优化、不同的执行引擎、不同的成本模型。本地通过的 SQL 可能在生产 Redshift 上行为不同(详见 10.6 改进项 #1)。


10.4 H&M 测试数据集

项目使用 Kaggle H&M Personalized Fashion Recommendations 作为端到端验证基线。数据集的完整介绍(来源、表结构、规模、选择理由、语义映射)见 附录 E

10.4.1 三张核心表

表名 类型 列数 说明
dim_article 维度表 26 商品属性(颜色、类别、部门等)
dim_customer 维度表 7 客户人口统计
fact_transaction 事实表 5 交易记录(客户 × 商品 × 时间 × 金额)

10.4.2 业务约束与语义资产

H&M 数据集有 7 条业务约束(如"退货金额为负""客户年龄匿名化"),在语义资产中体现为 business_rule。数据映射到 8 类语义资产,是三层治理模型的具体实例。

10.4.3 典型查询场景

以下 5 个场景覆盖了 TTD 的主要路由路径:

  1. "上月销量 Top 10 商品"(ranking)
  2. "华东区 GMV 同比趋势"(trend_analysis)
  3. "各品类销售占比"(comparison)
  4. "客户分群分析"(analytical_workflow → clustering)
  5. "退货率异常检测"(analytical_workflow → anomaly)

场景展开:上月销量 Top 10 商品

以场景 1 为例,展示从自然语言到 SQL 到结果的完整链路:

用户问题(before):"上月销量 Top 10 商品"

TTD 处理: - Query Understanding:intent=ranking,entities=[商品, 销量],temporal=上月 - Router:映射到 nl2sql_query - Data Retrieval:术语"销量"绑定 met_hm_transaction_count,"商品"绑定 dim_article - Semantic Planner:Steiner 树规划 fact_transaction ⋈ dim_article - SQL Generation:生成 SQL

生成的 SQL(after)

SELECT a.prod_name, COUNT(*) AS sales_count
FROM gold_hm.fact_transaction f
JOIN gold_hm.dim_article a ON f.article_id = a.article_id
WHERE f.t_dat >= DATE_TRUNC('month', CURRENT_DATE - INTERVAL '1 month')
  AND f.t_dat < DATE_TRUNC('month', CURRENT_DATE)
GROUP BY a.prod_name
ORDER BY sales_count DESC
LIMIT 10;

执行结果(片段)

prod_name sales_count
(商品名 1) 12,345
(商品名 2) 11,876
... ...

可视化:规则推荐条形图(ranking 场景),LLM 生成"上月 Top 1 商品为 XX,销量 12,345"的洞察。


10.5 数据平面性能与健康监控

10.5.1 性能(设计目标)

性能与质量指标(设计目标)

以下为数据面的设计目标值,TTD 尚未进行系统化实测(未做 TPC-H 或微基准测试):

指标 设计目标 说明
OLAP 聚合查询延迟(pg_mooncake) < 500ms 千万级行的 GROUP BY 聚合
OLAP 聚合查询延迟(Redshift) < 200ms 生产列存引擎
列存 vs 行存加速比 5-10x 聚合查询场景(设计预期)
查询超时 30s(TTD_STATEMENT_TIMEOUT_MS 硬上限
最大返回行数 1000(TTD_MAX_ROWS 硬上限
最大扫描字节 1GB(TTD_MAX_SCANNED_BYTES 硬上限

上述加速比与延迟为设计预期,改进方向:引入 TPC-H 或自定义微基准做系统化测量(第 16 章)。

10.5.2 数据平面健康监控

监控指标 说明 告警阈值(设计目标)
连接池饱和度 PG_POOL_MAX - active_connections < 2(即将耗尽)
查询超时率 超时查询数 / 总查询数 > 5%
列存同步滞后 _src 源表与列存镜像的同步延迟 > 60s
查询失败率 执行失败数 / 总执行数 > 2%
平均查询延迟 P50 / P95 执行时间 P95 > 5s

10.6 方案选型对比

10.6.1 本地数据栈对比

维度 TTD (PG Supernode + pg_mooncake + MinIO) DuckDB 单机 纯 Redshift 本地模拟
检索引擎 R/V/G/D 四引擎 仅关系 仅关系
列存 pg_mooncake 原生列存
对象存储 MinIO 文件系统
与生产一致性 中(pg_mooncake ≠ Redshift)
运维 中(多容器)

10.6.2 PG Supernode 一体化 vs 存算分离

维度 PG Supernode 一体化(TTD) 存算分离
运维 低(单实例) 高(多服务)
事务一致 强(共享事务)
性能 高(专用引擎)
规模
TTD 选择理由 开发态一体化降低运维,生产态可演进到存算分离

当前实现可改进之处

  1. 本地与生产差异大:开发用 pg_mooncake(PostgreSQL 方言),生产用 Redshift(Redshift 方言)。两者 SQL 语法有差异(如 DISTKEY/SORTKEY),本地通过的 SQL 可能在生产失败。改进:用 sqlglot 做方言转译测试,CI 中对同一查询跑双方言校验。
  2. 缺数据新鲜度保证:列存镜像是手动同步(load_hm_data.py),无自动增量同步。生产中数据更新后列存可能滞后。改进:引入 CDC(Change Data Capture)或定时增量同步管道。
  3. 列存同步靠脚本_src 源表 → mooncake.create_table() 列存镜像靠脚本手动触发,易遗忘。改进:自动化列存创建与刷新,随语义资产发布联动。
  4. 单一数据集验证:只在 H&M 数据集上验证,schema 规模小(3 表),无法暴露大规模 schema 下的检索与生成问题。改进:引入 Spider/BIRD 等多 schema 基准。

改进方向

数据面的演进方向是缩小开发/生产差异 + 自动化数据同步。短期:双方言 CI 校验、自动化列存同步。长期:抽象 DataPlane 接口让执行后端可插拔(Redshift/Snowflake/DuckDB),支持本地用 DuckDB 完整模拟生产查询语义。


10.7 小结与延伸阅读

本章要点

  1. Data Plane 含 PG Supernode(R/V/G/D 四引擎 + 会话)、pg_mooncake(列存)、MinIO(对象存储)。
  2. PG Supernode 一体化策略:R/V/G 共享一个 PG 实例,事务一致、运维简单。
  3. Schema 深潜:semlayer.metric_asset 等 17 张关系表 + 8 张 *_embedding 表(HNSW 索引,vector(1024))+ AGE 图 ttd_governance
  4. 双数据面后端(Redshift/pg_mooncake)通过环境变量切换,SQL 方言在执行前由 sqlglot 转译。
  5. pg_mooncake 列存镜像加速 OLAP 聚合,但 ≠ Redshift(方言与执行引擎不同)。
  6. H&M 数据集(3 表)作为端到端验证基线,映射到 8 类语义资产(详见 附录 E)。

延伸阅读

下一章第 11 章 Backend 服务参考——API 端点、生命周期、数据库模型与配置参考。