# tradehk 数据库与存储 > 返回:[tradehk 文档中心](./README.md) > 源文件:`drizzle/schema.ts`、`server/db.ts`、`server/storage.ts` ## 概述 tradehk 使用 MySQL 8.0 作为持久化存储,通过 Drizzle ORM 进行类型安全的数据库操作。主要存储:用户信息、用户配置、监控列表、交易信号记录。 --- ## 数据库表结构 ### users 表(用户) | 字段 | 类型 | 说明 | |------|------|------| | id | INT AUTO_INCREMENT | 主键 | | name | VARCHAR(255) | 显示名称 | | username | VARCHAR(255) UNIQUE | 用户名 | | email | VARCHAR(255) UNIQUE | 邮箱 | | passwordHash | VARCHAR(255) | 密码哈希(bcrypt)| | createdAt | DATETIME | 创建时间 | | updatedAt | DATETIME | 更新时间 | --- ### user_settings 表(用户配置) | 字段 | 类型 | 说明 | |------|------|------| | id | INT AUTO_INCREMENT | 主键 | | userId | INT | 外键 → users.id | | configJson | TEXT | JSON 格式的完整用户配置(UserConfig) | | updatedAt | DATETIME | 更新时间 | **configJson 结构**:存储 `UserConfig` 的完整 JSON 序列化,包含时区、指标参数、通知配置、EWO 规则等。 --- ### watchlist 表(监控列表) | 字段 | 类型 | 说明 | |------|------|------| | id | INT AUTO_INCREMENT | 主键 | | userId | INT | 外键 → users.id | | symbol | VARCHAR(20) | 交易对(如 "BTCUSDT")| | isActive | BOOLEAN | 是否在活跃监控列表中 | | sortOrder | INT | 排列顺序 | | createdAt | DATETIME | 创建时间 | --- ### signals 表(交易信号记录) | 字段 | 类型 | 说明 | |------|------|------| | id | INT AUTO_INCREMENT | 主键 | | userId | INT | 外键 → users.id | | symbol | VARCHAR(20) | 交易对 | | interval | VARCHAR(10) | K线周期(如 "10m")| | direction | ENUM('long','short') | 信号方向 | | strength | ENUM('strong','medium','weak') | 信号强度 | | score | INT | 信号评分(80/50/30)| | price | DECIMAL(20,8) | 信号价格 | | ewo | DECIMAL(20,8) | EWO 值(可空)| | macd | DECIMAL(20,8) | MACD 值(可空)| | macdSignal | DECIMAL(20,8) | MACD 信号线值(可空)| | macdHist | DECIMAL(20,8) | MACD 柱状图值(可空)| | ao | DECIMAL(20,8) | AO 值(可空)| | reasons | TEXT | JSON 字符串,原因列表(可空)| | signalAt | BIGINT | 信号时间戳(毫秒)| | createdAt | DATETIME | 记录创建时间 | **索引**:`(userId, symbol, interval, direction, signalAt)` 联合唯一索引,用于信号去重。 --- ## 内存缓存(pairCache / tickerCache) 除 MySQL 外,tradehk 还维护两个内存缓存: ### pairCache(K线缓存) ```typescript Map ``` **键格式**:`"{symbol}__{interval}"`,如 `"BTCUSDT__10m"` **更新时机**:每次引擎轮询时,通过 `refreshCacheForPairs` 从 Binance API 拉取最新数据。 ### tickerCache(行情缓存) ```typescript Map ``` **键格式**:`"{symbol}"`,如 `"BTCUSDT"` --- ## 关键数据库操作 ### 信号去重检查 ```typescript // hasSignalRecord 函数 // 检查同一用户、同一币对、同一方向、同一时间戳的信号是否已存在 SELECT COUNT(*) FROM signals WHERE userId = ? AND symbol = ? AND interval = ? AND direction = ? AND signalAt = ? ``` ### 信号窗口查询 ```typescript // getSignalsInWindow 函数 // 用于定期汇总通知 SELECT * FROM signals WHERE userId = ? AND signalAt BETWEEN ? AND ? ORDER BY signalAt DESC LIMIT ? ``` ### EWO 转换去重槽 EWO 转换去重使用 Redis 风格的共享槽(实际存储在 MySQL 的 `dedup_slots` 表中): ```typescript // consumeSharedEwoTurnDedupeSlot 函数 // 原子性地检查并占用去重槽 // 返回 true 表示允许推送,false 表示已推送过 ``` --- ## 数据库维护 ### 数据增长估算 假设监控 10 个币对,每个币对每小时产生 2 个信号: | 时间 | 信号记录数 | 磁盘占用(估算)| |------|-----------|----------------| | 1 天 | 480 条 | < 1 MB | | 1 周 | 3,360 条 | < 5 MB | | 1 月 | 14,400 条 | < 20 MB | | 1 年 | 175,200 条 | < 250 MB | **结论**:signals 表增长缓慢,一般不需要特别清理。但如果监控大量币对或使用高频周期,建议设置定期清理任务。 ### 清理过期信号 ```sql -- 清理30天前的信号记录 DELETE FROM signals WHERE signalAt < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) * 1000; ``` ### 数据库备份 ```bash # 完整备份 docker compose exec mysql mysqldump -u root -p tradehk > backup_$(date +%Y%m%d).sql # 只备份 signals 表 docker compose exec mysql mysqldump -u root -p tradehk signals > signals_backup_$(date +%Y%m%d).sql ``` --- ## Drizzle ORM 使用说明 tradehk 使用 Drizzle ORM 进行类型安全的数据库操作。 ### 运行迁移 ```bash # 生成迁移文件 pnpm drizzle-kit generate # 执行迁移 pnpm drizzle-kit migrate ``` ### 查看迁移历史 ```bash ls drizzle/migrations/ ``` --- ## 相关文档 - [系统架构总览](./系统架构总览.md) — 数据流向 - [类型系统参考](./类型系统参考.md) — Signal 类型定义 - [部署运维指南](./部署运维指南.md) — 数据库备份和维护