# Profeto 数据库与数据管线审查报告 **审查日期**: 2026-09-16 **审查范围**: 6 张表 ORM、6 个迁移文件、3 个采集器、上下文构建器、API 路由、连接池配置 **结论**: 发现 6 个 P1 + 5 个 P2 问题(无 P0) --- ## P1 级问题(6 个) ### P1-1: context_builder.py session 管理 - **文件**: `src/llm/context_builder.py` - **问题**: 每个切片函数独立创建 session。回测 20 场并发需 120 个连接,池仅 15 个 → 耗尽阻塞 - **修复**: build_context 创建共享 session 并传给所有切片函数,切片函数新增可选 `db` 参数 ### P1-2: bzzoiro.py 内存预加载 - **文件**: `src/data/bzzoiro.py` - **问题**: 预加载联赛全部比赛到内存(`select(Match).where(Match.league_id == league.id)`),多赛季采集时内存溢出 - **修复**: 改为按 raw_events 日期范围 ±30 天按需加载 ### P1-3: understat.py N+1 查询 - **文件**: `src/data/understat.py` - **问题**: 逐条查询比赛(每场 3 次 DB 往返),单赛季 380 次 = 1140 次往返 - **修复**: 批量查询球队(1 次) + 批量查询比赛(1 次) + 内存匹配 ### P1-4: injuries.py 幂等检查竞态条件 - **文件**: `src/data/injuries.py` - **问题**: check-then-insert 模式,并发采集触发 IntegrityError 导致整批回滚 - **修复**: 批量幂等检查 + 分批 flush + 失败回退逐条插入 ### P1-5: predict.py 同步 Lock 用于 async - **文件**: `src/llm/predict.py` - **问题**: `threading.Lock` 用于 async 函数,阻塞事件循环 - **修复**: 删除 Lock,dict 操作在 CPython GIL 下原子 ### P1-6: models.py 缺唯一约束 - **文件**: `src/db/models.py` - **问题**: 缺 `(match_id, provider, model)` 唯一约束,重复预测导致统计偏差 - **修复**: 添加 UniqueConstraint + 迁移文件 --- ## P2 级问题(5 个) ### P2-1: unit_of_work 类型注解错误 - **文件**: `src/db/unit_of_work.py` - **问题**: `AsyncIterator[AsyncSessionLocal]` 应为 `AsyncIterator[AsyncSession]` ### P2-2: normalize.py 日期解析静默丢弃 - **文件**: `src/data/normalize.py` - **问题**: `_parse_date` 失败返回 None,数据丢失无感知 - **修复**: 解析失败时 `logger.warning` 记录原始值 ### P2-3: repositories.py func.date() 索引失效 - **文件**: `src/db/repositories.py` - **问题**: `func.date(Match.match_date)` 致索引失效,全表扫描 - **修复**: 改用 `Match.match_date_date` 等值匹配 ### P2-4: 迁移 0005 幽灵列 - **文件**: `alembic/versions/0005` - **问题**: `cutoff_at` 列被注释掉未删除,autogenerate 噪声 - **状态**: 已在 0006 迁移中修复 ### P2-5: 迁移 0003 约束命名不一致 - **文件**: `alembic/versions/0003_injuries.py` - **问题**: UniqueConstraint vs ORM 的 Index(unique=True) 不一致 - **修复**: 新迁移 0007 将 UniqueConstraint 替换为唯一索引 --- ## 值得肯定的设计 - 索引/约束设计合理(唯一约束防重、CHECK 约束、复合索引) - 数据血缘追踪(source / retrieved_at / available_at)完善 - 采集管线有重试、限速、防回测泄漏 - `get_db` / `get_db_read` 读写分离 - 迁移规范,有 downgrade --- ## 修复验证 - [x] 全部文件语法检查通过 - [x] 11 个文件修改 + 2 个新迁移 - [x] MR #3 已提交: https://git.bilidili.cn/shangfangjian/Profeto/pulls/3 - [ ] 合并后运行 `alembic upgrade head` - [ ] 20 场并发回测压测验证连接池