数据库设计.md 33 KB

数据库设计

本文引用的文件

  • sql/gateway.sql
  • sql/user.sql
  • sql/agent_expert.sql
  • sql/agent_tool.sql
  • sql/chat_attachment.sql
  • sql/ai_clean.sql
  • sql/ai_clean_field_short_names.sql
  • sql/ai_clean_row_stats.sql
  • sql/ai_clean_synonym_init.sql
  • sql/ai_clean_template_drop_case_src.sql
  • sql/case_table.sql
  • sql/external_tables.sql
  • sql/external_table_field.sql
  • sql/insight_agent_tables.sql
  • sql/insight_agent_tables_align.sql
  • sql/plat.sql

目录

  1. 引言
  2. 项目结构与数据边界
  3. 核心业务域与表结构
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 初始化脚本执行顺序与迁移规范
  8. 性能与索引建议
  9. 数据安全、访问控制与备份恢复
  10. 故障排查指南
  11. 结论

引言

本设计文档梳理本项目在 PostgreSQL 主库中的持久化数据结构,覆盖网关路由、用户与授权、Agent 专家与工具、聊天附件、清洗模板与同义词、行统计、案件动态表、外部数据表、研判会话消息、平台元数据等。同时说明 pgvector 向量表与 DuckDB 临时数据源的用途差异,给出 ER 关系图、关键字段定义、主外键、索引约束和业务规则,并补充初始化顺序、迁移规范和回滚注意事项。

项目结构与数据边界

项目 SQL 脚本集中在 sql/ 目录,按业务功能拆分:

  • 网关路由:gateway.sql
  • 用户体系与案件归属:user.sql
  • Agent 专家与工具:agent_expert.sql、agent_tool.sql
  • 聊天附件:chat_attachment.sql
  • AI 清洗链路:ai_clean.sql、ai_clean_field_short_names.sql、ai_clean_row_stats.sql、ai_clean_synonym_init.sql、ai_clean_template_drop_case_src.sql
  • 案件动态表:case_table.sql、create_table_2.sql
  • 外部数据表:external_tables.sql、external_table_field.sql
  • 研判会话消息:insight_agent_tables.sql、insight_agent_tables_align.sql
  • 平台元数据:plat.sql

    graph TB
    PG["PostgreSQL 主库"]
    subgraph "系统配置"
        GW["gateway_service / gateway_node<br/>gateway_user_route"]
        SYS["sys_user"]
        AG["agent<br/>agent_tool"]
    end
    subgraph "对话与附件"
        ATT["chat_attachment"]
        INS_S["agent_insight_session"]
        INS_M["agent_insight_message"]
    end
    subgraph "AI 清洗"
        TPL["ai_clean_template / ai_clean_field"]
        RULE["ai_clean_rule"]
        JOB["ai_clean_job / ai_clean_batch"]
        SYN["ai_clean_synonym"]
    end
    subgraph "案件数据"
        CT["case_table.*<br/>DuckDB 动态表"]
        EXT["external_tables.*<br/>DuckDB 外部数据"]
    end
    subgraph "平台元数据"
        PLAT["plat.sql 中的 table_info / table_field<br/>chat_session / chat_model 等"]
    end
    
    SYS --> GW
    SYS --> INS_S
    SYS --> JOB
    SYS --> ATT
    TPL --> JOB
    RULE --> JOB
    SYN --> TPL
    ATT --> INS_M
    CT --> PLAT
    EXT --> PLAT
    

图表来源

  • sql/gateway.sql:1-107
  • sql/user.sql:1-75
  • sql/agent_expert.sql:1-47
  • sql/agent_tool.sql:1-52
  • sql/chat_attachment.sql:1-39
  • sql/ai_clean.sql:1-214
  • sql/insight_agent_tables.sql:1-107
  • sql/case_table.sql:1-200
  • sql/external_tables.sql:1-200
  • sql/plat.sql:1-154

章节来源

  • sql/gateway.sql:1-107
  • sql/user.sql:1-75
  • sql/agent_expert.sql:1-47
  • sql/agent_tool.sql:1-52
  • sql/chat_attachment.sql:1-39
  • sql/ai_clean.sql:1-214
  • sql/insight_agent_tables.sql:1-107
  • sql/case_table.sql:1-200
  • sql/external_tables.sql:1-200
  • sql/plat.sql:1-154

核心业务域与表结构

网关服务与节点

表名 主键 关键字段 约束与索引 业务含义
gateway_service id VARCHAR(64) name、path_prefix、login_path、health_path、default_node_id、enabled path_prefix 唯一;enabled 默认 1 一个对外路径前缀对应一组后端节点,首次启动可从配置播种
gateway_node id VARCHAR(64) service_id、name、base_url、enabled service_id + base_url 唯一;外键指向 gateway_service.id 一台后端 ai-server 实例
gateway_user_route id BIGSERIAL service_id、user_id、username、node_id ck_gateway_user_route_owner 保证至少一个用户标识;部分唯一索引分别约束 user_id 和 lower(username);node_id 有普通索引;两个外键分别指向服务和节点 用户粘性绑定到某个节点,不可用时返回 503,不自动切换

业务规则:

  • path_prefix 全局唯一,不能以 / 结尾,且不是 /gateway。
  • base_url 不含上下文路径,同一服务内地址必须唯一。
  • 用户绑定支持先按用户名预绑定,再关联真实用户 ID。

章节来源

  • sql/gateway.sql:1-107

用户与授权

表名 主键 关键字段 约束与索引 业务含义
sys_user id BIGSERIAL username、pwd_hash、display_name、is_admin、status、last_login_time lower(username) 唯一;is_admin 仅控制是否可调用用户管理接口;status 默认启用 系统认证用户,不实现角色菜单权限体系
case_info id INTEGER(自增) owner_id BIGINT(新增列) 对 owner_id 建索引 案件归属用户,仅创建者可见;存量未归属案件统一归给内置管理员

注意:

  • 本项目明确不做 sys_role、sys_menu、sys_permission、sys_user_role 等完整权限体系。
  • case_info.owner_id 是应用层“允许同名案件”的归属边界,数据库侧只加索引,不加唯一约束。

章节来源

  • sql/user.sql:1-75

Agent 专家与工具

表名 主键 关键字段 约束与索引 业务含义
agent row_id(通过脚本补主键) user_id、is_builtin、skills_allow_json、tools_allow_json user_id 有索引;内置专家全局可见不可编辑;非内置专家按创建者隔离 智能体配置,内置标记区分平台级和用户级
agent_tool id BIGINT tool_name、tool_class、tool_method、group_code、parameters、status tool_name 唯一;status 取 ACTIVE 或 DELETED 启动时反射扫描 @Tool 后 upsert 的工具清单,页面只读

业务规则:

  • 内置专家 is_builtin=1,归属平台管理员;用户自建专家 is_builtin=0,按 user_id 过滤。
  • 已删除代码中的工具保留行,状态置为 DELETED,便于追溯。
  • 脚本会修复历史重复主键、对齐序列,并补主键约束。

章节来源

  • sql/agent_expert.sql:1-47
  • sql/agent_tool.sql:1-52

聊天附件

表名 主键 关键字段 约束与索引 业务含义
chat_attachment id BIGINT user_id、case_id、session_id、file_name、file_path、sidecar_path、mime、kind、size_bytes、char_count、row_count、truncated、inline_text、index_blocks、index_status、link_message_id、fail_reason 索引:session_id、status+link_message_id 附件问答三路的元数据锚点:内联文本、Python 直读文件、RAG 分块向量化

业务规则:

  • 三路处理:A 内联小文档、B Python 大表格、C RAG 大文档。
  • 加载时必须校验 user_id/case_id/session_id 三重归属。
  • RAG 向量侧另按会话过滤,检索 SQL 强制带 sessionId。

章节来源

  • sql/chat_attachment.sql:1-39

清洗模板、字段、规则与任务

表名 主键 关键字段 约束与索引 业务含义
ai_clean_template id BIGINT table_name_cn、table_name_en、headers、header_md5、func_regex、struct_ops、needs_struct、category、match_tier、status、ver、confidence header_md5 唯一;status、category 有索引 AI 模板,等价于既有 table_info,但完全独立存储
ai_clean_field id BIGINT ai_template_id、column_name、field_name_cn、field_name_en、field_type、required、field_len、field_sort、col_index、matched 按 ai_template_id 索引 动态表 DDL 真源,物理列固定为 c0/c1/…
ai_clean_rule id BIGINT ai_template_id、col_index、field_name_en、hints、ref_template_id 按 ai_template_id 索引 扁平枚举 hint 的规则快照,避免反序列化任意类
ai_clean_job id BIGINT case_id、file_id、sheet_id、block_no、ver、status、exit_code、token_in/out、cost_ms、row_total/loaded/rejected/warned/unprocessed 唯一键 (case_id, file_id, sheet_id, block_no, ver);status、file_id 有索引 幂等游标 + 状态线 + 成本埋点
ai_clean_batch id BIGINT case_id、batch_id、stage、file_count、sheet_total、matched_count、ai_judged_count、loaded_rows、rejected_rows、unprocessed_rows、self_built_count 唯一键 (case_id, batch_id);stage 有索引 智能清洗批次状态机
ai_clean_synonym id BIGINT std_word、alias_word、remark、status (std_word, alias_word) 唯一 表头同义词星型词组,用于评分和绑定域

重要变更:

  • ai_clean_field.column_name 与 field_name_en 统一为 c{位置},宽度收窄为 VARCHAR(5)。
  • 新增行统计列:job.row_rejected、job.row_warned、job.row_unprocessed,以及 batch.loaded_rows、rejected_rows、unprocessed_rows、self_built_count。
  • 同义词表可通过管理接口运行期维护,内置词条由初始化脚本填充。
  • 模板不再记录 case_id_src,跨案件共享。

章节来源

  • sql/ai_clean.sql:1-214
  • sql/ai_clean_field_short_names.sql:1-16
  • sql/ai_clean_row_stats.sql:1-21
  • sql/ai_clean_synonym_init.sql:1-42
  • sql/ai_clean_template_drop_case_src.sql:1-10

案件动态表

case_table.sql 中定义了多个案件相关表,例如:

  • trans_record、trans_record_all:交易流水
  • call_record、call_record_all:通话记录
  • use_open_info_call_record:开户信息通话记录
  • account_opening_info:账户开户信息

这些表通常作为 DuckDB 临时数据源使用,包含高频定位列的索引约定,如姓名、身份证号、卡号、手机号、证件号等。

章节来源

  • sql/case_table.sql:1-200

外部数据表

external_tables.sql 描述来自“表结构信息.txt”的外部数据表,包括:

  • cert_info:出入境证件信息
  • entry_rec:出入境记录
  • vehicle_info:机动车信息
  • lic_info:驾驶证信息
  • veh_violation:机动车违章
  • household:同户人
  • co_resident:同住址
  • co_veh_viol:同车违章
  • criminal:违法犯罪人员信息

这些表与 external_table_field.sql 一起,映射到平台 table_info 与 table_field,用于外部数据语义检索。

章节来源

  • sql/external_tables.sql:1-200
  • sql/external_table_field.sql:1-80

研判会话与消息

表名 主键 关键字段 约束与索引 业务含义
agent_insight_session id BIGINT case_id、biz_type、scope、agent_row_id、model_id、title、context、context_hash、sys_prompt、message_count、last_seq、total_tokens、last_message_at、pinned、status case_id+biz_type+last_message_at 列表索引;case_id+context_hash 复用索引 独立于通用对话表的研判会话,强制案件级隔离
agent_insight_message id BIGINT session_id、case_id、seq、role、content、content_type、message_type、metadata、tool_events、output_json、token_count、reply_to_message_id、starred、status 唯一键 (session_id, seq);外键级联删除会话;case_id+create_at 部分索引过滤结构化产物 研判消息,排序列必须是 seq

注意:

  • 初次建表用 insight_agent_tables.sql;已有库需用 insight_agent_tables_align.sql 补齐约束与索引。
  • seq 通过 UPDATE ... RETURNING last_seq 原子分配,禁止 SELECT MAX(seq)+1。

章节来源

  • sql/insight_agent_tables.sql:1-107
  • sql/insight_agent_tables_align.sql:1-88

平台元数据

plat.sql 包含一些平台基础表和旧版聊天元数据,例如:

  • bank_card_issuer_info:银行卡发卡方
  • case_info:案件基础信息
  • phone_isp:手机号运营商归属
  • system_info:系统激活信息
  • table_info、table_field:表与字段元数据
  • chat_message、chat_session、chat_model、chat_provider、knowledge_attach、knowledge_fragment、knowledge_info

这些表与 AI 清洗、外部数据、图谱等业务配合,但不直接承载主业务流程的核心行数据。

章节来源

  • sql/plat.sql:1-154

架构总览

erDiagram
    sys_user {
        bigint id PK
        varchar username
        varchar pwd_hash
        smallint is_admin
        smallint status
        timestamp last_login_time
    }

    gateway_service {
        varchar id PK
        varchar name
        varchar path_prefix UK
        varchar login_path
        varchar health_path
        varchar default_node_id
        smallint enabled
    }

    gateway_node {
        varchar id PK
        varchar service_id FK
        varchar name
        varchar base_url
        smallint enabled
    }

    gateway_user_route {
        bigint id PK
        varchar service_id FK
        bigint user_id
        varchar username
        varchar node_id FK
    }

    agent {
        bigint row_id PK
        bigint user_id
        smallint is_builtin
        text skills_allow_json
        text tools_allow_json
    }

    agent_tool {
        bigint id PK
        varchar tool_name UK
        varchar tool_class
        varchar tool_method
        varchar group_code
        jsonb parameters
        varchar status
    }

    chat_attachment {
        bigint id PK
        bigint user_id
        bigint case_id
        bigint session_id
        varchar file_name
        varchar file_path
        varchar kind
        integer row_count
        varchar status
    }

    ai_clean_template {
        bigint id PK
        varchar header_md5 UK
        varchar table_name_en
        varchar status
        numeric confidence
    }

    ai_clean_field {
        bigint id PK
        bigint ai_template_id
        varchar column_name
        varchar field_name_en
        varchar field_type
    }

    ai_clean_rule {
        bigint id PK
        bigint ai_template_id
        integer col_index
        text hints
    }

    ai_clean_job {
        bigint id PK
        bigint case_id
        bigint file_id
        bigint sheet_id
        integer block_no
        integer ver
        varchar status
        integer row_rejected
        integer row_warned
        integer row_unprocessed
    }

    ai_clean_batch {
        bigint id PK
        bigint case_id
        bigint batch_id
        varchar stage
        bigint loaded_rows
        bigint rejected_rows
        bigint unprocessed_rows
    }

    ai_clean_synonym {
        bigint id PK
        varchar std_word
        varchar alias_word
    }

    agent_insight_session {
        bigint id PK
        bigint case_id
        varchar biz_type
        bigint model_id
        jsonb context
        varchar context_hash
        bigint last_seq
        varchar status
    }

    agent_insight_message {
        bigint id PK
        bigint session_id FK
        bigint case_id
        bigint seq
        varchar role
        jsonb output_json
        varchar status
    }

    sys_user ||--o{ gateway_user_route : "绑定"
    gateway_service ||--o{ gateway_node : "包含"
    gateway_service ||--o{ gateway_user_route : "路由范围"
    agent ||--o{ agent_insight_session : "可选使用"
    ai_clean_template ||--o{ ai_clean_field : "包含字段"
    ai_clean_template ||--o{ ai_clean_rule : "包含规则"
    ai_clean_job ||--o{ ai_clean_batch : "属于批次"
    agent_insight_session ||--o{ agent_insight_message : "包含消息"
    chat_attachment ||--o{ agent_insight_message : "可选关联"

图表来源

  • sql/gateway.sql:1-107
  • sql/user.sql:1-75
  • sql/agent_expert.sql:1-47
  • sql/agent_tool.sql:1-52
  • sql/chat_attachment.sql:1-39
  • sql/ai_clean.sql:1-214
  • sql/insight_agent_tables.sql:1-107

详细组件分析

网关粘性路由流程

sequenceDiagram
    participant Client as "客户端"
    participant Gateway as "ai-gateway"
    participant Service as "gateway_service"
    participant Node as "gateway_node"
    participant Route as "gateway_user_route"
    participant Server as "ai-server 实例"

    Client->>Gateway: "请求 /js/a/... 路径"
    Gateway->>Service: "根据 path_prefix 查找服务"
    Service-->>Gateway: "返回服务配置"
    Gateway->>Route: "按 user_id 或 lower(username) 查绑定"
    Route-->>Gateway: "返回 node_id"
    Gateway->>Node: "检查节点可用"
    alt "节点可用"
        Gateway->>Server: "转发原始路径"
        Server-->>Client: "响应"
    else "节点不可用"
        Gateway-->>Client: "返回 503"
    end

图表来源

  • sql/gateway.sql:1-107

章节来源

  • sql/gateway.sql:1-107

清洗模板匹配与入库流程

flowchart TD
    Start(["上传文件"]) --> Parse["解析表头与内容"]
    Parse --> Fingerprint["计算 header_md5"]
    Fingerprint --> Match{"命中既有模板?"}
    Match -->|是| Existing["走出口 A:复用既有模板"]
    Match -->|否| LLM["调用模型判定结构"]
    LLM --> SaveTpl["保存 ai_clean_template / ai_clean_field"]
    SaveTpl --> Rule["生成 ai_clean_rule"]
    Rule --> Job["写入 ai_clean_job"]
    Existing --> Batch["写入 ai_clean_batch"]
    Rule --> Batch
    Batch --> Validate["逐行校验类型/必填/长度"]
    Validate --> Load{"是否通过"}
    Load -->|是| Insert["写入 DuckDB 动态表"]
    Load -->|否| Reject["计入 rejected_rows / row_rejected"]
    Insert --> Done(["批次完成"])
    Reject --> Partial["部分成功"]
    Partial --> Done

图表来源

  • sql/ai_clean.sql:1-214

章节来源

  • sql/ai_clean.sql:1-214

研判会话消息写入流程

sequenceDiagram
    participant User as "用户"
    participant Session as "agent_insight_session"
    participant Message as "agent_insight_message"
    participant DB as "PostgreSQL"

    User->>Session: "发起研判会话"
    Session->>DB: "INSERT session (case_id, biz_type, context)"
    DB-->>Session: "返回 session.id"
    User->>Message: "发送消息"
    Message->>DB: "UPDATE session SET last_seq = last_seq + 1 RETURNING last_seq"
    DB-->>Message: "返回 seq"
    Message->>DB: "INSERT message (session_id, case_id, seq, role, content)"
    DB-->>User: "返回消息结果"

图表来源

  • sql/insight_agent_tables.sql:1-107
  • sql/insight_agent_tables_align.sql:1-88

章节来源

  • sql/insight_agent_tables.sql:1-107
  • sql/insight_agent_tables_align.sql:1-88

依赖关系分析

graph LR
    SYS["sys_user"] --> GWU["gateway_user_route"]
    GWS["gateway_service"] --> GWN["gateway_node"]
    GWS --> GWU
    GWN --> GWU

    AG["agent"] --> INS_S["agent_insight_session"]

    TPL["ai_clean_template"] --> FL["ai_clean_field"]
    TPL --> RU["ai_clean_rule"]
    TPL --> JB["ai_clean_job"]
    SY["ai_clean_synonym"] --> TPL

    JB --> BA["ai_clean_batch"]

    ATT["chat_attachment"] --> INS_M["agent_insight_message"]
    INS_S --> INS_M

    CT["case_table.*"] --> PT["platform meta"]
    EX["external_tables.*"] --> PT

图表来源

  • sql/gateway.sql:1-107
  • sql/user.sql:1-75
  • sql/agent_expert.sql:1-47
  • sql/ai_clean.sql:1-214
  • sql/insight_agent_tables.sql:1-107
  • sql/chat_attachment.sql:1-39

章节来源

  • sql/gateway.sql:1-107
  • sql/user.sql:1-75
  • sql/agent_expert.sql:1-47
  • sql/ai_clean.sql:1-214
  • sql/insight_agent_tables.sql:1-107
  • sql/chat_attachment.sql:1-39

初始化脚本执行顺序与迁移规范

推荐执行顺序

  1. 平台元数据:plat.sql
    • 建立 table_info、table_field、case_info、chat_*、knowledge_* 等基础表。
  2. 用户体系:user.sql
    • 创建 sys_user,插入内置管理员,为 case_info 添加 owner_id 并回填。
  3. 网关路由:gateway.sql
    • 创建 gateway_service、gateway_node、gateway_user_route,并建立外键与索引。
  4. Agent 专家:agent_expert.sql
    • 补齐 agent.user_id、is_builtin、主键、序列和对齐逻辑。
  5. Agent 工具清单:agent_tool.sql
    • 人工执行一次,后续由应用启动反射同步。
  6. AI 清洗链路:ai_clean.sql
    • 创建模板、字段、规则、任务、批次、同义词表。
  7. 清洗字段列宽修正:ai_clean_field_short_names.sql
    • 将历史 field_name_en 与 column_name 对齐为 c{位置},收窄列宽。
  8. 清洗行统计扩展:ai_clean_row_stats.sql
    • 为 ai_clean_job 和 ai_clean_batch 增加行统计列。
  9. 清洗同义词初始化:ai_clean_synonym_init.sql
    • 为已有环境补建同义词表并插入内置词条。
  10. 移除模板案件来源列:ai_clean_template_drop_case_src.sql
    • 删除 ai_clean_template.case_id_src。
  11. 研判会话与消息:insight_agent_tables.sql
    • 空库首次建表;若表已存在,需继续执行对齐脚本。
  12. 研判会话约束对齐:insight_agent_tables_align.sql
    • 补齐 uk_aim_session_seq、fk_aim_session、列表索引、部分索引、注释。
  13. 案件动态表:case_table.sql、create_table_2.sql
    • 按需重建 DuckDB 临时表,注意主键和索引约定。
  14. 外部数据表与字段映射:external_tables.sql、external_table_field.sql
    • 创建外部数据表并写入 table_info、table_field。

迁移规范

  • 所有脚本均标注幂等性,优先使用 CREATE TABLE IF NOT EXISTS、ALTER TABLE ... ADD COLUMN IF NOT EXISTS、DROP CONSTRAINT IF EXISTS、CREATE INDEX IF NOT EXISTS。
  • 涉及锁升级的约束修改(如唯一约束、外键)应设置 lock_timeout,避免长事务阻塞。
  • 不要在生产环境直接执行 DROP TABLE 脚本;现有脚本多为测试或演示用途,实际部署应改用增量迁移。
  • 对于 agent_tool,DDL 由人工执行一次,运行时只 upsert 数据。
  • 对于 insight_agent_tables,已有库必须执行 insight_agent_tables_align.sql,否则缺失唯一约束和外键会导致孤儿消息。

回滚注意事项

  • 删除列或表前确认没有外键引用;当前多数外键为 ON DELETE RESTRICT,可直接阻止危险删除。
  • 对 agent 主键修复和序列对齐脚本会清理脏数据,回滚前需备份。
  • 清洗模板移除 case_id_src 后,不应再通过该列做案件归属判断。
  • 同义词表初始化使用 on conflict do nothing,重复执行不会破坏数据。
  • 研判消息 seq 的唯一约束由 UPDATE ... RETURNING last_seq 和唯一索引共同保障,回滚后重新执行对齐脚本即可。

章节来源

  • sql/agent_tool.sql:1-52
  • sql/insight_agent_tables.sql:1-107
  • sql/insight_agent_tables_align.sql:1-88
  • sql/ai_clean_synonym_init.sql:1-42
  • sql/ai_clean_template_drop_case_src.sql:1-10

性能与索引建议

PostgreSQL 主库

  • 网关路由:
    • gateway_service.path_prefix 唯一索引保证路径分发稳定。
    • gateway_user_route 使用部分唯一索引分别约束 user_id 和 lower(username),避免并发冲突。
    • node_id 普通索引加速节点可用性查询。
  • 用户与授权:
    • sys_user.username 使用 lower() 唯一索引,兼容大小写不敏感登录。
    • case_info.owner_id 索引支持按归属用户过滤。
  • Agent 工具:
    • agent_tool.tool_name 唯一索引防止模型调用落到错误实现。
  • 清洗链路:
    • ai_clean_template.header_md5 唯一索引用于零模型重放。
    • ai_clean_job 唯一键保证同一文件块只处理一次。
    • ai_clean_batch 唯一键保证重复点击返回同一批次。
    • ai_clean_synonym 唯一键防止标准词与别名组合重复。
  • 研判会话:
    • agent_insight_session 列表索引按 case_id、biz_type、last_message_at 排序。
    • context_hash 索引用于同条件复用。
    • agent_insight_message 唯一键 (session_id, seq) 防重号。
    • 部分索引 idx_aim_output 只索引有结构化产出的消息。

DuckDB 临时数据源

  • 主要面向单案分析,利用 zonemap 和少量 ART 索引优化高频定位列。
  • 时间、日期、金额等分析过滤依赖自动 zonemap,不建议盲目加索引。
  • 仅对人、卡、账号、手机、证件号等高频筛选列建索引。

pgvector 向量表

  • 聊天附件 RAG 路径 C 会为每个会话生成向量表,命名约定为 chat_att_vec_{caseId}_d{dims}。
  • 向量检索必须强制带 sessionId,避免跨会话泄露。
  • 向量表不在仓库 DDL 中显式声明,而是按维度动态生成;其生命周期与附件、会话、工作区强绑定。

章节来源

  • sql/gateway.sql:1-107
  • sql/agent_tool.sql:1-52
  • sql/ai_clean.sql:1-214
  • sql/insight_agent_tables.sql:1-107
  • sql/case_table.sql:1-200
  • sql/chat_attachment.sql:1-39

数据安全、访问控制与备份恢复

数据安全

  • 密码存储:sys_user.pwd_hash 使用 BCrypt 哈希,明文不得进入脚本或日志。
  • 敏感字段:chat_attachment.file_path、sidecar_path、inline_text 可能包含隐私数据,应限制文件系统访问权限。
  • 向量表:chat_att_vec_{caseId}_d{dims} 包含文档切片向量,应按会话隔离访问。
  • 工具参数:agent_tool.parameters 存 JSON Schema,不应直接拼接执行。
  • 清洗规则:ai_clean_rule.hints 使用枚举 hint,避免反序列化任意 Java 类。
  • 研判提示词:agent_insight_session.sys_prompt 仅运维追溯,不通过接口下发。

访问控制

  • 用户权限:仅 is_admin=1 可调用用户管理接口,前端静态菜单仍由本地配置生成。
  • 网关粘性:用户绑定节点失败时返回 503,不自动切换到其他节点,避免越权路由。
  • 研判会话:所有查询强制携带 case_id,消息表冗余 case_id 以强化 SQL 层隔离。
  • 附件加载:必须校验 user_id/case_id/session_id,任一不匹配即拒绝。

备份恢复建议

  • 主库:
    • 定期备份 sys_user、gateway_*、agent、agent_tool、chat_attachment、ai_clean_*、agent_insight_*。
    • 重点保护 pwd_hash、context、sys_prompt、tool_events、output_json 等高价值或高敏感字段。
  • 向量表:
    • 按会话维度备份,避免误删他人向量数据。
    • 恢复时需重建对应 d{dims} 维度的向量表。
  • DuckDB 临时表:
    • 一般可按案件重建;若需要离线分析,应单独归档原始文件和 DuckDB 数据文件。
  • 迁移回滚:
    • 先停写,再回滚数据,最后执行反向 DDL。
    • 对含外键的表,应先解除引用或删除子表数据。

章节来源

  • sql/user.sql:1-75
  • sql/chat_attachment.sql:1-39
  • sql/insight_agent_tables.sql:1-107
  • sql/agent_tool.sql:1-52
  • sql/ai_clean.sql:1-214

故障排查指南

用户无法登录或账号被顶下线

  • 检查 sys_user.status 是否为启用。
  • 检查 sys_user.pwd_hash 是否为有效 BCrypt 值。
  • 网关粘性路由异常时,确认 gateway_user_route 是否存在对应用户绑定。

章节来源

  • sql/user.sql:1-75
  • sql/gateway.sql:1-107

Agent 主键重复或序列异常

  • 执行 agent_expert.sql 清理重复行、对齐序列并补主键。
  • 确认 agent.row_id 已有主键约束。

章节来源

  • sql/agent_expert.sql:1-47

工具清单为空或不同步

  • 确认已执行 agent_tool.sql。
  • 检查 agent_tool.tool_name 是否有重复值。
  • 查看应用启动日志是否提示执行脚本。

章节来源

  • sql/agent_tool.sql:1-52

清洗任务重复或状态不一致

  • 检查 ai_clean_job 唯一键是否命中。
  • 核对 ai_clean_batch 唯一键是否重复触发。
  • 查看 row_rejected、row_warned、row_unprocessed 定位失败原因。

章节来源

  • sql/ai_clean.sql:1-214
  • sql/ai_clean_row_stats.sql:1-21

研判会话消息重号或缺失

  • 确认已执行 insight_agent_tables_align.sql。
  • 检查 uk_aim_session_seq 是否存在。
  • 检查 fk_aim_session 是否级联删除。
  • 确认 seq 通过 UPDATE ... RETURNING last_seq 原子分配。

章节来源

  • sql/insight_agent_tables.sql:1-107
  • sql/insight_agent_tables_align.sql:1-88

附件无法加载或向量检索越界

  • 校验 chat_attachment.session_id、user_id、case_id。
  • 确认 RAG 向量表存在且按会话过滤。
  • 检查 index_status 是否为 READY。

章节来源

  • sql/chat_attachment.sql:1-39

结论

本项目 PostgreSQL 主库采用多业务域分离设计:网关路由、用户认证、Agent 专家与工具、聊天附件、AI 清洗链路、研判会话消息、案件动态表和外部数据表各司其职。PG 负责持久化、一致性、会话隔离和审计追踪;DuckDB 承担案件级临时分析和外部数据快速查询;pgvector 向量表按会话和维度动态组织,服务于 RAG 检索。迁移应以幂等脚本为主,严格遵循初始化顺序,并在生产环境谨慎执行 DROP 操作。安全方面重点保护密码、向量数据、提示词、工具参数和案件归属关系,备份恢复应覆盖主库、向量表和 DuckDB 临时数据。