
1) 【一句话结论】:采用三表关联设计(毕业生信息、就业单位、就业数据),通过外键建立业务关联,新增“是否签订三方协议”字段细化就业状态,结合复合索引与毕业年份分区表优化查询性能,并设计增量刷新的物化视图,平衡数据一致性与查询效率。
2) 【原理/概念讲解】:数据库表设计需遵循第三范式(3NF),减少冗余。外键(FK)用于关联表间数据,确保数据一致性(如毕业生表主键“学号”作为就业数据表的外键,保证每个就业记录对应唯一毕业生)。索引是加速查询的工具:主键索引唯一标识记录,外键索引加速关联查询,普通索引加速单列查询(如按专业统计),复合索引用于多条件查询(如专业+就业状态)。就业数据表中“是否签订三方协议”字段(0=未签,1=已签)是关键,用于区分不同就业状态,避免就业率统计偏差。类比:毕业生表是“学生档案”,就业单位表是“工作单位信息”,就业数据表是“就业合同记录”,外键是“学生与合同的关联”,索引是“快速找到某个学生的合同信息”,就业状态字段是“合同的有效性标识”。
3) 【对比与适用场景】:
| 索引类型 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 主键索引 | 表唯一标识列的索引,自增 | 唯一、唯一性约束 | 表主键(如学号) | 不能为空,自动创建 |
| 外键索引 | 关联表的外键列索引 | 唯一或非唯一(外键约束) | 关联表(如就业数据表学号) | 级联操作(如删除父表记录时处理子表) |
| 普通索引 | 非唯一列的索引 | 非唯一 | 单列查询(如按专业统计) | 索引列不能为空(空值索引无效) |
| 复合索引 | 多列组合的索引 | 非唯一 | 复合条件查询(如专业+就业状态) | 顺序影响查询效率(前缀匹配优先) |
4) 【示例】:
CREATE TABLE GraduateInfo (
student_id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
major VARCHAR(50),
graduation_year INT,
INDEX idx_major (major) -- 普通索引,加速按专业统计
);
CREATE TABLE EmploymentUnit (
unit_id INT PRIMARY KEY,
unit_name VARCHAR(100) NOT NULL,
industry VARCHAR(50),
location VARCHAR(100),
INDEX idx_industry (industry) -- 普通索引,按行业筛选
);
CREATE TABLE EmploymentData (
record_id INT PRIMARY KEY,
student_id INT NOT NULL,
unit_id INT NOT NULL,
employment_date DATE,
position VARCHAR(100),
employment_status INT DEFAULT 0, -- 0=未就业,1=已就业(签订三方),2=已就业(未签三方)
is_triple_agree INT DEFAULT 0, -- 是否签订三方协议(0=否,1=是)
FOREIGN KEY (student_id) REFERENCES GraduateInfo(student_id) ON DELETE CASCADE, -- 删除毕业生时删除就业记录
FOREIGN KEY (unit_id) REFERENCES EmploymentUnit(unit_id) ON DELETE SET NULL, -- 单位删除时,就业记录单位设为NULL
INDEX idx_student_id (student_id), -- 外键索引,加速关联
INDEX idx_unit_id (unit_id), -- 外键索引
INDEX idx_employment_status (employment_status), -- 索引就业状态,加速就业率统计
INDEX idx_is_triple_agree (is_triple_agree) -- 索引三方协议状态,细化统计
);
CREATE TABLE EmploymentData (
record_id INT,
student_id INT,
unit_id INT,
employment_date DATE,
position VARCHAR(100),
employment_status INT,
is_triple_agree INT,
graduation_year INT,
PRIMARY KEY (record_id),
FOREIGN KEY (student_id) REFERENCES GraduateInfo(student_id),
FOREIGN KEY (unit_id) REFERENCES EmploymentUnit(unit_id),
PARTITION BY RANGE (graduation_year) (
PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION p2026 VALUES LESS THAN (2027),
PARTITION p2027 VALUES LESS THAN MAXVALUE
)
);
CREATE MATERIALIZED VIEW employment_rate_view AS
SELECT major, COUNT(*) as employed_count, COUNT(*) as total_count
FROM GraduateInfo g
JOIN EmploymentData e ON g.student_id = e.student_id
WHERE e.employment_status = 1 AND e.is_triple_agree = 1 -- 仅统计已签三方的就业
GROUP BY g.major;
CREATE OR REPLACE MATERIALIZED VIEW employment_rate_view AS
WITH updated_data AS (
SELECT major, COUNT(*) as employed_count, COUNT(*) as total_count
FROM GraduateInfo g
JOIN EmploymentData e ON g.student_id = e.student_id
WHERE e.employment_status = 1 AND e.is_triple_agree = 1
GROUP BY g.major
)
SELECT * FROM updated_data;
CREATE EVENT refresh_employment_rate
ON SCHEDULE EVERY 1 DAY STARTS NOW
DO
REFRESH MATERIALIZED VIEW employment_rate_view;
5) 【面试口播版答案】:面试官您好,针对毕业生就业数据存储,我设计三表结构:毕业生信息表(存储学号、姓名、专业、毕业年份)、就业单位表(存储单位ID、名称、行业、地点)、就业数据表(记录就业关联及就业状态,新增“是否签订三方协议”字段细化就业情况)。关系上,毕业生表主键“学号”作为就业数据表的外键,就业单位表主键“单位ID”作为就业数据表的外键,实现一对多关联(一个毕业生对应多个就业记录,一个单位对应多个毕业生)。索引设计:毕业生表专业列加普通索引,加速按专业统计;就业数据表学号、单位ID、就业状态、三方协议状态列加索引,加速关联与就业率查询。针对就业率统计(如按专业统计已签三方的就业率),创建物化视图存储统计结果,并采用增量刷新策略,减少实时计算压力。外键级联操作:删除毕业生时自动删除就业记录,单位删除时就业记录单位设为NULL,保证数据一致性。数据量增大时,按毕业年份对就业数据表进行分区,提升查询性能。这样既保证数据完整,又提升查询效率。
6) 【追问清单】:
7) 【常见坑/雷区】: