跳转至

分布式数据库适配方案


0. 耦合点流程图与清单

0.1 整体流程图

┌─────────────────────────────────────────────────────────────────┐
│  config.ini: db_mode = centralized | distributed                │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│  TDSQLClient.__init__()                                         │
│  读取 db_mode → self.db_mode                                    │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
          ┌──────────────────┴──────────────────┐
          │  ★ 分支点 1:execute_explain()      │
          │                                      │
          ├─ centralized ──► EXPLAIN ANALYZE     │
          └─ distributed ──► EXPLAIN             │
          └──────────────────┬──────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│  node_load_inputs()                                             │
│  ★ 分支点 2:构建 distributed_context                            │
│                                                                  │
│  ┌─ centralized ─► distributed_context = {}                     │
│  │                                                               │
│  └─ distributed ─► build_distributed_context()                  │
│         │                                                        │
│         ├─ analyze_distributed_explain()                         │
│         │     └─ 正则扫描 Exchange/Shuffle/Gather/...            │
│         │                                                        │
│         └─ load_table_distributed_metadata()                     │
│               ├─ 解析 ddl.sql (shardkey/PARTITION BY/BROADCAST)  │
│               ├─ 解析 partitions.json                            │
│               └─ 读取 distributed.json (手动覆盖)                │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│  V3State {db_mode, distributed_context, ...}                    │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│  node_build_prompt() → build_prompt_round1()                    │
│  ★ 分支点 3:模板变量替换                                        │
│                                                                  │
│  {db_arch_label} = centralized → "TDSQL(集中式)"               │
│                  = distributed → "TDSQL(分布式)"               │
│  {db_mode}       = centralized | distributed                    │
│  {distributed_context} = centralized → ""                       │
│                       = distributed → JSON 串                   │
└────────────────────────────┬────────────────────────────────────┘
                             │
                             ▼
┌─────────────────────────────────────────────────────────────────┐
│  Prompt 模板 opt_v3.3.0.txt                                     │
│  ★ 分支点 4:上下文段落                                          │
│                                                                  │
│  ┌─ 集中式 ──► distributed_context 段为空                       │
│  └─ 分布式 ──► 显示分片键、EXPLAIN 算子、missing_info           │
└────────────────────────────┬────────────────────────────────────┘
                             │
   ╔═══════════════════════════╧═══════════════════════════════╗
   ║                    共享路径(零耦合)                        ║
   ║                                                             ║
   ║  ┌─────────────────────────────────────────────────────┐   ║
   ║  │ node_call_llm()  ── 调 LLM,与 db_mode 无关          │   ║
   ║  └─────────────────────────────────────────────────────┘   ║
   ║                          ▼                                  ║
   ║  ┌─────────────────────────────────────────────────────┐   ║
   ║  │ node_parse_llm() ── 解析 JSON,与 db_mode 无关       │   ║
   ║  └─────────────────────────────────────────────────────┘   ║
   ║                          ▼                                  ║
   ║  ┌─────────────────────────────────────────────────────┐   ║
   ║  │ node_persist()   ── 落盘 JSON,与 db_mode 无关       │   ║
   ║  └─────────────────────────────────────────────────────┘   ║
   ║                          ▼                                  ║
   ║  ┌─────────────────────────────────────────────────────┐   ║
   ║  │ node_execute()  ── 走 TDSQLClient(已在分支点 1)    │   ║
   ║  └─────────────────────────────────────────────────────┘   ║
   ║                          ▼                                  ║
   ║  ┌─────────────────────────────────────────────────────┐   ║
   ║  │ build_execution_feedback() ── 纯数值比较,无关        │   ║
   ║  └─────────────────────────────────────────────────────┘   ║
   ║                          ▼                                  ║
   ║  ┌─────────────────────────────────────────────────────┐   ║
   ║  │ node_stop()     ── 停止策略,与 db_mode 无关          │   ║
   ║  └─────────────────────────────────────────────────────┘   ║
   ╚═════════════════════════════════════════════════════════════╝

0.2 耦合点清单

分支点 位置 触发条件 现状
1. EXPLAIN 命令 TDSQLClient.execute_explain() db_mode == "distributed" 已实现
2. distributed_context 构建 node_load_inputs() db_mode == "distributed" 待实现
3. Prompt 变量替换 build_prompt_round1() db_mode 待实现
4. Prompt 模板段落 opt_v3.3.0.txt {distributed_context} 是否为空 待实现

0.3 关键观察

只有 4 个耦合点,全部集中在流程前端(输入收集 + Prompt 构建)。

node_call_llm 往后的所有节点(LLM 调用、解析、持久化、执行、反馈、停止判断)完全共享代码路径,与 db_mode 无关。这意味着:

  • 集中式回归测试覆盖了 80%+ 的共享路径
  • 分布式只增加 4 个 if 分支,风险可控
  • 改动影响范围收敛,不需要全流程测试

主要风险点在分支点 2(DDL 解析),因为 TDSQL 的分片语法不是标准 SQL,正则识别容易漏判。建议这个分支点加 fallback 到 missing_info,不要因解析失败阻塞流程。


1. 现有入口与缺口

1.1 现有入口

能力 当前位置 状态
数据库模式配置 config.ini.exampledb_mode = centralized/distributed 已有入口
分布式 EXPLAIN 分支 core/tdsql_client/client.py:execute_explain() distributed 使用 EXPLAIN
表上下文采集 core/dataprocess_v3/table_ctx/* 已采集 DDL、索引、分区、统计信息

1.2 当前缺口

  • Prompt 顶部仍写死集中式描述
  • 缺少 distributed_context 结构
  • 缺少分片键 / 路由信息合并逻辑
  • 缺少分布式 EXPLAIN 算子结构化识别

2. 收集的信息清单

2.1 表级信息(每张涉及的表)

信息项 用途 来源优先级
分片键 shard_keys 判断是否单分片查询、Join 是否对齐 DDL > partitions.json > 手动补充
分区方式 partition_method 区分 HASH / RANGE / LIST partitions.json
分区表达式 partition_expression 辅助判断分片键 partitions.json
分区数 partition_count 评估扫描规模 partitions.json
表行数 table_rows 评估表规模 复用现有 table_stats.json
是否广播表 is_broadcast_table 识别广播表避免误判 DDL 中的 BROADCAST 关键字
索引作用域 index_scope 区分局部/全局索引 DDL 中的 GLOBAL INDEX 关键字;无法判断时标记 local_unknown

2.2 SQL 级信息(针对目标 SQL)

信息项 用途 来源
EXPLAIN 分布式算子 operators 判断跨分片执行形态 EXPLAIN 文本扫描
是否跨分片 has_cross_shard 风险标记 算子集合推断
是否全分片扫描 has_full_shard_scan 风险标记 算子集合推断
是否广播 has_broadcast 辅助理解执行策略 算子集合推断
执行证据 raw_evidence 给 LLM 看的原文片段 EXPLAIN 文本

2.3 EXPLAIN 扫描识别的算子

算子类别 关键词 含义
Exchange / Shuffle Exchange, Shuffle, HashShuffle, Redistribute 跨节点数据重分布
Gather / Merge Gather, Gather Merge, Merge 多分片结果汇总
Broadcast Broadcast 小表广播
Motion Motion, Redistribute Motion, Broadcast Motion PostgreSQL 系数据移动
Scatter Scatter, all shards, full shard 全分片扫描
TDSQL HashQuery QueryMode: Hash proxy Hash 模式组织查询
TDSQL ProxyDeduplicate ProxyDeduplicate proxy 层去重/聚合
TDSQL SetRewrite set_数字_数字 proxy 拆解/改写为中间集合

2.4 DDL 关键字识别规则

DDL 关键字 提取目标 说明
shardkey=col / SHARD KEY (col) shard_keys TDSQL 私有语法
PARTITION BY HASH(col) shard_keys, partition_method, partition_expression MySQL 原生分区,可能是分片键
PARTITION BY RANGE/LIST(...) partition_method, partition_expression 通常是分区不是分片
BROADCAST is_broadcast_table=true TDSQL 广播表
GLOBAL INDEX index_scope=global 全局索引
LOCAL INDEX / 无标记 index_scope=local_unknown 需 DBA 确认默认值

2.5 信息缺失处理

无法识别的字段必须落入 missing_info,不要静默失败:

  • 分片键无法识别 → missing_info 记录"缺少 {table} 的分片键"
  • 索引作用域无法判断 → missing_info 记录"无法判断 {table} 索引作用域"
  • information_schema.partitions 返回 NULL ≠ 没有分片键,只是未暴露

2.6 采集范围收敛原则

  • 默认只采集当前 SQL 引用的表,不做全库扫描
  • 表数 <= 5 时全采;> 5 时只采 Top 5(驱动表、最大事实表、Join 两侧大表、WHERE 过滤最多的表)
  • 小码表、字典表后置,缺分片信息不阻塞主表判断
  • 表行数复用现有 table_stats.json,不重复查询

3. 信息采集命令

目标数据库已按分布式库处理,本节只保留表级和 SQL 级证据采集命令。

3.1 每类检查的用处

检查项 主要用处 能证明什么 不能证明什么 优先级
information_schema.partitions 查看 MySQL 原生分区信息和表行数估计 是否暴露 PARTITION_METHODPARTITION_EXPRESSION;辅助判断表规模 TDSQL 分片键可能不在这里暴露;返回 NULL 不能说明没有分片 辅助
SHOW CREATE TABLE 确认表结构、索引定义、分片语法 是否有 shardkeySHARD KEYPARTITION BYGLOBAL INDEX;是判断分片键的最关键证据 厂商隐藏分片元数据时 DDL 也看不到 必查
SHOW INDEX FROM 查看已有索引列顺序和基数 当前是否已有可用索引;是否可能重复建索引 通常看不出是否跨分片;不一定能看出局部/全局作用域 建议查
目标 SQL 的整体 EXPLAIN 判断 SQL 实际执行形态 是否出现 QueryMode: HashProxyDeduplicateset_...ExchangeShuffle 等分布式执行证据 不能直接给出表的分片键;局部输出可能漏掉关键算子 必查
单表过滤 EXPLAIN 判断单表访问路径 WHERE 是否命中索引;type/key/rows/filtered 是否健康 不能证明单分片或跨分片;不能替代整体 EXPLAIN 辅助

3.2 使用原则

  • 写方案阶段不需要补齐所有命令输出,只记录需要采集的证据和缺失项
  • 真正评估某条 SQL 时,优先拿"整体 EXPLAIN + 关键表 SHOW CREATE TABLE"
  • 单表 EXPLAIN 只用于解释索引命中,不用于判断分布式安全性
  • 表很多时不要全查,只查主表、大表、Join 两侧表;其余表写入 missing_info

3.3 必查命令

目标表 DDL 和分片键

SHOW CREATE TABLE db_name.table_name\G

重点看 shardkeySHARD KEYPARTITION BYDISTRIBUTED BYBROADCASTGLOBAL INDEX。表多时先查数据量最大的 2-3 张事实表。

分区/分片表达式

SELECT table_schema, table_name, partition_name,
       partition_method, partition_expression, table_rows
FROM information_schema.partitions
WHERE table_schema = 'db_name'
  AND table_name IN ('table1', 'table2')
ORDER BY table_name, partition_ordinal_position;

目标 SQL 是否跨分片

EXPLAIN SELECT ...;

输出重点保留含以下关键词的行:ExchangeShuffleGatherBroadcastMotionScatterQueryModeProxyDeduplicateset_remoteall shardpartition


4. 工作流接入方向

4.1 配置层

config.ini 中分布式库新增 db_mode = distributed 配置项(已有入口,无需改动)。

4.2 State 层

V3State 新增两个字段: - db_mode: 标识当前数据库模式 - distributed_context: 存储采集到的分布式上下文(集中式为空)

4.3 输入加载层

node_load_inputs()db_mode == "distributed" 时触发分布式上下文采集: - 扫描目标 SQL 的 EXPLAIN 文本,识别分布式算子 - 对涉及的表,从 table_ctx/ 目录加载分布式元数据(分片键、广播表、索引作用域) - 把采集结果写入 distributed_context,落入 missing_info 的项不阻塞流程

4.4 Prompt 构建层

build_prompt_round1()db_mode == "distributed" 时把分布式上下文注入 Prompt: - 数据库架构标签动态切换(集中式 ↔ 分布式) - 在列选择性之后追加分布式上下文段(集中式时该段为空) - 不改变现有 Prompt 的其他结构

4.5 共享路径(无改动)

以下节点与 db_mode 完全无关,不需要任何改动:

节点 不改动原因
node_call_llm() LLM 调用与架构无关
node_parse_llm() JSON 解析与架构无关
node_persist() 落盘逻辑与架构无关
node_execute() 已走 TDSQLClient(分支点 1 已处理)
build_execution_feedback() 纯数值比较
node_stop() 停止策略与架构无关

5. 实施计划

Phase 1:最小可落地

目标:跑通一条分布式 SQL 的端到端优化,Prompt 中能看到分布式上下文。

主要工作: - 新增独立模块承载分布式上下文采集逻辑(EXPLAIN 扫描 + 表元数据合并) - State 层加 db_modedistributed_context 两个字段 - node_load_inputs() 中按 db_mode 分支构建上下文 - Prompt 模板增加 {db_mode}{db_arch_label}{distributed_context} 占位符 - 集中式路径行为零变化(所有改动在 db_mode == "distributed" 分支内)

Phase 2:DDL 解析增强

目标:自动识别主流分布式 DDL 语法,减少对 DBA 手动补充的依赖。

主要工作: - TDSQL shardkey / SHARD KEY 语法识别 - MySQL 原生 PARTITION BY HASH 语法识别(区分 RANGE/LIST) - BROADCAST 广播表识别 - GLOBAL INDEX 全局索引识别 - distributed.json 手动覆盖机制(DBA 优先级最高)

验证标准

  • 集中式路径(db_mode=centralized)行为零变化,回归测试全部通过
  • 分布式路径下 Prompt 中能看到 distributed_context
  • missing_info 能正确反映未采集到的表和字段
  • DDL 解析能识别至少 3 种分片语法(TDSQL shardkey、MySQL PARTITION BY HASH、BROADCAST)

风险点

风险 影响 缓解
TDSQL DDL 样本缺失 正则写不对 先跑测试 SQL 拿真实 DDL,再写解析
Prompt 模板改动影响 LLM 输出质量 优化效果回退 集中式回归 + 分布式小批量验证
分片语法识别不全 missing_info 频繁出现 接受降级,依赖 DBA 手动补充