Files
platform-pipi/packages/design-document/database-design.md
T
2026-02-09 13:30:43 +08:00

484 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 字词学习平台 - 数据库设计文档
## 1. 数据库选型
### 1.1 推荐方案:PostgreSQL
**选择理由:**
-**关系型数据优势**:字词、关联关系、用户等数据具有强关联性,适合关系型数据库
-**JSON 支持**PostgreSQL 原生支持 JSON/JSONB,可以灵活存储 SVG 数据
-**全文搜索**:内置全文搜索功能,适合字词搜索场景
-**扩展性强**:支持数组类型,适合存储多个拼音、多个读音等
-**成熟稳定**:企业级数据库,性能优秀
-**开源免费**:成本可控
### 1.2 备选方案
**MySQL 8.0+**
- 优势:生态成熟,使用广泛
- 劣势:JSON 支持不如 PostgreSQL 完善
**MongoDB**
- 优势:文档型数据库,灵活性强
- 劣势:关联查询复杂,不适合强关联关系场景
## 2. 数据库分离设计
### 2.1 核心设计思路
**字和词分离为两个独立的数据库**
**设计原则:**
1.**汉字数据库**:专门存储汉字相关数据,包含汉字的特有属性(笔画、结构、部首等)
2.**词语数据库**:专门存储词语相关数据,包含词语的组成和关联关系
3.**数据隔离**:字和词的数据结构差异较大,分离后更便于管理和优化
4.**扩展性好**:后续如需支持英语单词,可单独设计英语数据库
**注意:**
- 英语展示不考虑和汉字放在一个库
- 当前版本先完成汉字数据库的设计和实现
- 词语数据库表暂时设计,后续实现
## 3. 汉字数据库设计
### 3.1 汉字主表 (chars)
存储汉字的基础信息。
```sql
CREATE TABLE chars (
id BIGSERIAL PRIMARY KEY,
char VARCHAR(10) NOT NULL UNIQUE COMMENT '汉字内容,如"中"',
strokes INT NOT NULL COMMENT '笔画数',
pinyin TEXT[] NOT NULL COMMENT '拼音数组,支持多音字,如["zhōng", "zhòng"]',
radicals VARCHAR(10) COMMENT '偏旁部首',
frequency INT COMMENT '使用频率: 0(最常用), 1(较常用), 2(次常用), 3(二级字), 4(三级字), 5(生僻字)',
structure VARCHAR(10) COMMENT '汉字结构代码,如"D0"(独体结构), "H2"(左窄右宽)等',
traditional VARCHAR(50) COMMENT '繁体字写法,可能有多个,用逗号分隔',
stroke_data JSONB COMMENT '笔画数据,JSON格式,存储笔画顺序和路径信息',
grade INT COMMENT '年级: 0-9NULL表示未设置',
description TEXT COMMENT '描述信息',
status VARCHAR(20) DEFAULT 'active' COMMENT '状态: active(启用), inactive(禁用)',
-- 索引
INDEX idx_char (char),
INDEX idx_strokes (strokes),
INDEX idx_pinyin (pinyin),
INDEX idx_radicals (radicals),
INDEX idx_frequency (frequency),
INDEX idx_structure (structure),
INDEX idx_grade (grade),
INDEX idx_status (status)
);
-- 全文搜索索引
CREATE INDEX idx_char_fulltext ON chars USING GIN (to_tsvector('simple', char));
```
**字段说明:**
- `char`: 汉字内容,唯一不重复,如"中"
- `strokes`: 笔画数,整数类型
- `pinyin`: PostgreSQL 数组类型,存储多个拼音,支持多音字
- `radicals`: 偏旁部首,如"中"的部首是"丨"
- `frequency`: 使用频率,0为最常用,1为较常用,2为次常用,3为二级字,4为三级字,5为不在《通用规范汉字》的生僻字
- `structure`: 汉字结构代码,参考结构代码表(见 `structure_codes.json`),如"D0"(独体结构)、"H2"(左窄右宽)等
- `traditional`: 繁体字写法,可能有多个,用逗号分隔,如"乾幹"
- `stroke_data`: JSONB 类型,存储笔画数据,包含笔画顺序和路径信息(原 svg_data 字段)
- `grade`: 年级,0-9年级,NULL 表示未设置
- `status`: 启用/禁用状态,支持软删除
**说明:** 音频文件已迁移至 `char_readings` 表,按音义项分别存储。
**结构代码说明:**
- 结构代码定义见 `structure_codes.json` 文件
- 常见结构代码:D0(独体结构)、D1(镶嵌结构)、B1-B4(上下结构)、H1-H3(左右结构)、R1-R6(半包围结构)等
### 3.2 汉字音义项表 (char_readings)
存储每个汉字在不同读音/含义下的信息,支持多音字、多义字。单音字一条记录,多音字/同音多义字多条记录。
```sql
CREATE TABLE char_readings (
id BIGSERIAL PRIMARY KEY,
char_id BIGINT NOT NULL,
pinyin VARCHAR(20) NOT NULL COMMENT '读音,如 zhōng、zhòng',
meaning VARCHAR(200) COMMENT '义项说明,同音多义时用于区分,如"中间;中心"、"击中;符合"',
introduce TEXT NOT NULL COMMENT '该音义项下的提示语',
audio_file_ref VARCHAR(500) COMMENT '音频相对路径,与配置中的 base URL 拼接,如 audio/chars/中/zhōng.mp3',
image_file_ref VARCHAR(500) COMMENT '图片相对路径,可选,幼小低年级字才有释义图',
sort_order INT DEFAULT 0 COMMENT '排序,常用音义可放前面',
FOREIGN KEY (char_id) REFERENCES chars(id) ON DELETE CASCADE,
INDEX idx_char_id (char_id),
INDEX idx_pinyin (pinyin),
INDEX idx_char_pinyin (char_id, pinyin)
);
```
**字段说明:**
- `char_id`: 关联的汉字ID
- `pinyin`: 该音义项的读音
- `meaning`: 义项说明,同音多义时用于区分
- `introduce`: 该音义项下的提示语(如"中,中间的中")
- `audio_file_ref`: 音频相对路径,采用 relative 方案,与配置中的 base URL 拼接成完整地址
- `image_file_ref`: 图片相对路径,可选,仅部分字(如幼小低年级需掌握的字)有此字段
- `sort_order`: 排序,常用音义优先展示
**路径约定:**
- 音频、图片均使用 relative 方案,数据库仅存相对路径
- base URL 在应用配置中维护,迁移 CDN/域名时无需更新数据库
- 示例:`audio_file_ref = "audio/chars/中/zhōng.mp3"`,完整地址 = `{base_url}/{audio_file_ref}`
### 3.3 汉字图片表 (char_images)
存储汉字字形相关图片(原图、标准图等,与读音无关)。
```sql
CREATE TABLE char_images (
id BIGSERIAL PRIMARY KEY,
char_id BIGINT NOT NULL COMMENT '关联的汉字ID',
image_type VARCHAR(20) NOT NULL COMMENT '图片类型: original(原图), standard(标准图)',
file_path VARCHAR(500) NOT NULL COMMENT '图片文件路径',
file_name VARCHAR(200) NOT NULL COMMENT '原始文件名',
file_size BIGINT COMMENT '文件大小(字节)',
width INT COMMENT '图片宽度',
height INT COMMENT '图片高度',
mime_type VARCHAR(50) COMMENT 'MIME类型',
is_primary BOOLEAN DEFAULT FALSE COMMENT '是否为主图',
sort_order INT DEFAULT 0 COMMENT '排序顺序',
FOREIGN KEY (char_id) REFERENCES chars(id) ON DELETE CASCADE,
INDEX idx_char_id (char_id),
INDEX idx_image_type (image_type),
INDEX idx_is_primary (is_primary)
);
```
**字段说明:**
- `char_id`: 关联的汉字ID
- `image_type`: 区分原图和标准图
- `file_path`: 图片存储路径
- `is_primary`: 标记主图,用于列表展示
- `sort_order`: 排序字段,支持多图排序
### 3.4 汉字关联表 (char_relations)
存储汉字之间的关联关系(如形近字、同音字等)。
```sql
CREATE TABLE char_relations (
id BIGSERIAL PRIMARY KEY,
source_char_id BIGINT NOT NULL COMMENT '源汉字ID',
target_char_id BIGINT NOT NULL COMMENT '目标汉字ID',
relation_type VARCHAR(20) NOT NULL COMMENT '关联类型: similar_shape(形近字), same_pinyin(同音字), same_radical(同部首), similar_structure(同结构)',
sort_order INT DEFAULT 0 COMMENT '排序顺序',
FOREIGN KEY (source_char_id) REFERENCES chars(id) ON DELETE CASCADE,
FOREIGN KEY (target_char_id) REFERENCES chars(id) ON DELETE CASCADE,
UNIQUE (source_char_id, target_char_id, relation_type),
INDEX idx_source_char (source_char_id),
INDEX idx_target_char (target_char_id),
INDEX idx_relation_type (relation_type)
);
```
**关联类型说明:**
- `similar_shape`: 形近字,如"人"和"入"
- `same_pinyin`: 同音字,如"中"和"钟"
- `same_radical`: 同部首,如"中"和"串"
- `similar_structure`: 同结构,如都是左右结构
### 3.5 句子表 (sentences)
存储字词关联的例句。
```sql
CREATE TABLE sentences (
id BIGSERIAL PRIMARY KEY,
content TEXT NOT NULL COMMENT '句子内容',
translation TEXT COMMENT '翻译(英语句子需要)',
audio_path VARCHAR(500) COMMENT '音频文件路径',
source VARCHAR(100) COMMENT '来源,如教材名称',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_content_fulltext (to_tsvector('simple', content))
);
```
### 3.6 汉字-句子关联表 (char_sentences)
存储汉字和句子的关联关系。
```sql
CREATE TABLE char_sentences (
id BIGSERIAL PRIMARY KEY,
char_id BIGINT NOT NULL COMMENT '汉字ID',
sentence_id BIGINT NOT NULL COMMENT '句子ID',
sort_order INT DEFAULT 0 COMMENT '排序顺序',
FOREIGN KEY (char_id) REFERENCES chars(id) ON DELETE CASCADE,
FOREIGN KEY (sentence_id) REFERENCES sentences(id) ON DELETE CASCADE,
UNIQUE (char_id, sentence_id),
INDEX idx_char_id (char_id),
INDEX idx_sentence_id (sentence_id)
);
```
### 3.7 用户表 (users)
存储管理员用户信息。
```sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',
email VARCHAR(100) UNIQUE COMMENT '邮箱',
password_hash VARCHAR(255) NOT NULL COMMENT '密码哈希',
role VARCHAR(20) NOT NULL DEFAULT 'admin' COMMENT '角色: super_admin(超级管理员), admin(一般管理员)',
real_name VARCHAR(50) COMMENT '真实姓名',
avatar VARCHAR(500) COMMENT '头像URL',
status VARCHAR(20) DEFAULT 'active' COMMENT '状态: active(启用), inactive(禁用)',
last_login_at TIMESTAMP COMMENT '最后登录时间',
last_login_ip VARCHAR(50) COMMENT '最后登录IP',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_username (username),
INDEX idx_email (email),
INDEX idx_role (role),
INDEX idx_status (status)
);
```
### 3.8 操作日志表 (operation_logs)
记录用户操作日志,用于审计。
```sql
CREATE TABLE operation_logs (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT COMMENT '操作用户ID',
action VARCHAR(50) NOT NULL COMMENT '操作类型: create, update, delete, upload等',
resource_type VARCHAR(50) NOT NULL COMMENT '资源类型: word, image, sentence等',
resource_id BIGINT COMMENT '资源ID',
description TEXT COMMENT '操作描述',
ip_address VARCHAR(50) COMMENT 'IP地址',
user_agent TEXT COMMENT '用户代理',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
INDEX idx_user_id (user_id),
INDEX idx_action (action),
INDEX idx_resource (resource_type, resource_id),
INDEX idx_created_at (created_at)
);
```
## 4. 词语数据库设计(暂时设计)
### 4.1 词语主表 (chinese_words)
存储词语的基础信息。
```sql
CREATE TABLE chinese_words (
id BIGSERIAL PRIMARY KEY,
word VARCHAR(100) NOT NULL UNIQUE COMMENT '词语内容,如"中国"',
pinyin TEXT[] COMMENT '拼音数组,如["zhōng", "guó"]',
grade INT COMMENT '年级: 0-9NULL表示未设置',
description TEXT COMMENT '词语解释',
audios TEXT[] COMMENT '音频文件路径数组',
status VARCHAR(20) DEFAULT 'active' COMMENT '状态: active(启用), inactive(禁用)',
-- 索引
INDEX idx_word (word),
INDEX idx_grade (grade),
INDEX idx_status (status)
);
-- 全文搜索索引
CREATE INDEX idx_word_fulltext ON chinese_words USING GIN (to_tsvector('simple', word));
```
### 4.2 词语-汉字关联表 (word_characters)
存储词语和组成汉字的关联关系。
```sql
CREATE TABLE word_characters (
id BIGSERIAL PRIMARY KEY,
word_id BIGINT NOT NULL COMMENT '词语ID',
char_id BIGINT NOT NULL COMMENT '汉字ID(关联到汉字数据库)',
position INT NOT NULL COMMENT '汉字在词语中的位置,从1开始',
FOREIGN KEY (word_id) REFERENCES chinese_words(id) ON DELETE CASCADE,
INDEX idx_word_id (word_id),
INDEX idx_char_id (char_id),
INDEX idx_position (position)
);
```
**注意:** 词语数据库和汉字数据库是分离的,`char_id` 字段存储的是汉字数据库中的汉字ID,需要通过跨库查询或应用层关联。
### 4.3 词语图片表 (word_images)
存储词语关联的图片信息。
```sql
CREATE TABLE word_images (
id BIGSERIAL PRIMARY KEY,
word_id BIGINT NOT NULL COMMENT '关联的词语ID',
image_type VARCHAR(20) NOT NULL COMMENT '图片类型: original(原图), standard(标准图)',
file_path VARCHAR(500) NOT NULL COMMENT '图片文件路径',
file_name VARCHAR(200) NOT NULL COMMENT '原始文件名',
file_size BIGINT COMMENT '文件大小(字节)',
width INT COMMENT '图片宽度',
height INT COMMENT '图片高度',
mime_type VARCHAR(50) COMMENT 'MIME类型',
is_primary BOOLEAN DEFAULT FALSE COMMENT '是否为主图',
sort_order INT DEFAULT 0 COMMENT '排序顺序',
FOREIGN KEY (word_id) REFERENCES chinese_words(id) ON DELETE CASCADE,
INDEX idx_word_id (word_id),
INDEX idx_image_type (image_type),
INDEX idx_is_primary (is_primary)
);
```
### 4.4 词语-句子关联表 (word_sentences)
存储词语和句子的关联关系。
```sql
CREATE TABLE word_sentences (
id BIGSERIAL PRIMARY KEY,
word_id BIGINT NOT NULL COMMENT '词语ID',
sentence_id BIGINT NOT NULL COMMENT '句子ID',
sort_order INT DEFAULT 0 COMMENT '排序顺序',
FOREIGN KEY (word_id) REFERENCES chinese_words(id) ON DELETE CASCADE,
FOREIGN KEY (sentence_id) REFERENCES sentences(id) ON DELETE CASCADE,
UNIQUE (word_id, sentence_id),
INDEX idx_word_id (word_id),
INDEX idx_sentence_id (sentence_id)
);
```
## 5. 数据库关系图
### 5.1 汉字数据库关系图
```
chars (汉字主表)
├── char_readings (音义项表) - 一对多,支持多音字、多义字
├── char_images (字形图片表) - 一对多
├── char_relations (汉字关联) - 自关联(多对多)
├── char_sentences (汉字-句子关联) - 多对多
└── operation_logs (操作日志) - 关联资源
char_readings (音义项表)
└── 存储 introduce、audio_file_ref、image_file_ref 等按读音/义项区分的数据
sentences (句子表)
└── char_sentences (汉字-句子关联) - 多对多
```
### 5.2 词语数据库关系图
```
chinese_words (词语主表)
├── word_characters (词语-汉字关联) - 多对多(跨库关联)
├── word_images (图片表) - 一对多
├── word_sentences (词语-句子关联) - 多对多
└── operation_logs (操作日志) - 关联资源
sentences (句子表)
└── word_sentences (词语-句子关联) - 多对多
```
### 5.3 公共表
```
users (用户表)
└── operation_logs (操作日志) - 一对多
sentences (句子表)
├── char_sentences (汉字-句子关联) - 多对多
└── word_sentences (词语-句子关联) - 多对多
```
## 6. 索引优化建议
### 6.1 汉字数据库查询优化索引
- 汉字内容索引:支持快速查找
- 笔画数索引:支持按笔画数筛选
- 拼音索引:支持按拼音查找
- 部首索引:支持按部首查找
- 结构代码索引:支持按结构筛选
- 频率索引:支持按使用频率筛选
- 全文搜索索引:支持模糊搜索
### 6.2 词语数据库查询优化索引
- 词语内容索引:支持快速查找
- 年级索引:支持按年级筛选
- 全文搜索索引:支持模糊搜索
### 6.3 关联查询优化
- 外键索引:所有外键字段建立索引
- 关联表索引:char_readings、char_relations、char_sentences、word_characters、word_sentences 的关联字段索引
## 7. 数据迁移策略
### 7.1 初始化数据
- 创建默认超级管理员账户
- 初始化年级数据字典(可选)
- 导入汉字结构代码数据(structure_codes.json
### 7.2 数据导入
- 支持批量导入汉字数据(参考 char_common_base.json 格式)
- 支持批量导入音义项数据(参考 char_introduce.json,需按多音/多义拆分为多条 char_readings
- 支持批量导入词语数据
- 支持 CSV/Excel 格式导入
### 7.3 数据迁移注意事项
- 从旧的 words 表迁移到 chars 表时,需要:
-`content` 字段映射到 `char` 字段
-`svg_data` 字段重命名为 `stroke_data`
- 补充 `strokes``pinyin``radicals``frequency``structure``traditional` 字段
- 过滤出 `type = 'chinese_char'` 的数据
- 从 char_introduce.json 迁移到 char_readings 时,需要:
- 单音字:每条 JSON 对应一条 char_readings 记录
- 多音字/多义字:需人工或脚本标注拆分,每个音义项一条 char_readings 记录
## 8. 数据备份策略
### 8.1 备份方案
- 每日全量备份
- 实时增量备份(可选)
- 汉字数据库和词语数据库分别备份
### 8.2 恢复方案
- 支持时间点恢复
- 定期恢复演练
## 9. 性能优化建议
### 9.1 查询优化
- 使用连接池管理数据库连接
- 复杂查询使用视图或物化视图
- 合理使用缓存(Redis
- 跨库查询(词语-汉字关联)建议在应用层实现,避免跨库JOIN
### 9.2 数据量预估
- 汉字数据:预计 8,000+ 条(通用规范汉字表)
- 音义项数据:预计 10,000~12,000 条(多音字对应多条记录)
- 词语数据:预计 10,000+ 条
- 图片数据:预计 50,000+ 条
- 关联关系:预计 100,000+ 条
### 9.3 分表策略(如需要)
- 当 chars 表数据量超过 100 万时,考虑按频率分表
- 当 chinese_words 表数据量超过 100 万时,考虑按年级分表
- 使用 PostgreSQL 分区功能