
1) 【一句话结论】采用“学生-知识点-题目-答题记录”四表关联设计,通过外键约束保证数据一致性,结合复合索引(覆盖查询字段)和分区(按学生ID哈希+按时间范围分区)优化查询性能,支持高效统计错题分布与排名。
2) 【原理/概念讲解】
讲解关系型数据库设计核心原则:
3) 【对比与适用场景】
| 对比维度 | 索引类型 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|---|
| 索引类型 | 主键索引 | 唯一自增字段 | 唯一性+快速定位 | 表主键 | 必须唯一,不能为NULL |
| 普通索引 | 单字段索引 | 单字段查询加速 | 单字段查询(如按学生ID查答题记录) | 单字段查询,无法支持多字段组合 | 单字段查询,避免选择性低字段前置 |
| 复合索引 | 多字段组合索引 | 多字段查询加速(前缀匹配) | 多字段查询(如按知识点+时间统计) | 多字段查询(如按知识点+时间统计错题) | 遵循“最左前缀原则”,避免选择性低字段前置 |
| 对比维度 | 分区类型 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|---|
| 分区类型 | 范围分区 | 按字段范围划分 | 数据有序,查询范围高效 | 按时间(如按答题时间范围分区) | 数据需有序,避免跨分区查询 |
| 哈希分区 | 按哈希函数划分 | 数据随机分布,查询均匀 | 按学生ID(如按学生ID哈希分区) | 按学生ID查询(如单学生错题统计) | 数据需均匀分布,避免哈希冲突 |
4) 【示例】
表结构设计(伪代码):
-- 学生表
CREATE TABLE student (
student_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL
);
-- 知识点表
CREATE TABLE topic (
topic_id INT PRIMARY KEY,
topic_name VARCHAR(100) NOT NULL
);
-- 题目表
CREATE TABLE question (
question_id INT PRIMARY KEY,
topic_id INT NOT NULL,
content TEXT,
FOREIGN KEY (topic_id) REFERENCES topic(topic_id)
);
-- 答题记录表
CREATE TABLE answer_record (
record_id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT NOT NULL,
question_id INT NOT NULL,
answer TEXT,
is_correct BOOLEAN NOT NULL, -- 0错1对
timestamp DATETIME NOT NULL,
FOREIGN KEY (student_id) REFERENCES student(student_id),
FOREIGN KEY (question_id) REFERENCES question(question_id)
);
-- 索引设计
CREATE INDEX idx_student_question ON answer_record(student_id, question_id, is_correct); -- 复合索引
CREATE INDEX idx_topic_wrong ON question(topic_id, is_correct) WHERE is_correct = 0; -- 覆盖索引
-- 分区设计
CREATE TABLE answer_record (
record_id INT PRIMARY KEY AUTO_INCREMENT,
student_id INT NOT NULL,
question_id INT NOT NULL,
answer TEXT,
is_correct BOOLEAN NOT NULL,
timestamp DATETIME NOT NULL,
FOREIGN KEY (student_id) REFERENCES student(student_id),
FOREIGN KEY (question_id) REFERENCES question(question_id)
) PARTITION BY HASH(student_id) PARTITIONS 10; -- 哈希分区
查询示例:
SELECT t.topic_name, COUNT(ar.is_correct) AS wrong_count
FROM answer_record ar
JOIN question q ON ar.question_id = q.question_id
JOIN topic t ON q.topic_id = t.topic_id
WHERE ar.is_correct = 0
GROUP BY t.topic_name
ORDER BY wrong_count DESC;
SELECT s.name, COUNT(ar.is_correct) AS wrong_count
FROM answer_record ar
JOIN student s ON ar.student_id = s.student_id
WHERE ar.is_correct = 0
GROUP BY s.name
ORDER BY wrong_count DESC
LIMIT 10;
5) 【面试口播版答案】
“面试官您好,针对竞赛教练分析学生答题数据的需求,我设计了一套基于MySQL的多表关联结构,并优化了查询性能。首先,核心思路是拆分数据为‘学生’‘知识点’‘题目’‘答题记录’四张表,通过外键关联保证数据一致性。比如学生表存储学生信息,知识点表存储知识点,题目表关联知识点和题目,答题记录表记录每个学生的答题情况(包括是否正确、时间等)。这样设计的好处是避免数据冗余,便于维护。然后,为了支持高效的查询,比如按知识点统计错题数,我会给答题记录表和题目表建复合索引(比如按学生ID、题目ID、是否正确排序),同时给题目表的‘知识点ID+是否正确’字段建覆盖索引,这样统计错题时可以直接用索引字段计算,无需回表。另外,针对数据量大的情况,我会对答题记录表按学生ID进行哈希分区(比如分成10个分区),这样查询某个学生的答题记录时,只需要访问对应分区,减少查询时间。总结来说,通过表结构设计、索引优化和分区策略,可以高效支持按知识点统计错题数、按学生统计错题排名等查询需求。”
6) 【追问清单】
ANALYZE TABLE)定期分析索引使用情况。)selected_options JSON数组),同时增加选项表(option表)存储题目选项,通过关联表记录学生选择的选项。)7) 【常见坑/雷区】