
1) 【一句话结论】针对按用户ID查询近30天课程完成率的场景,应采用复合索引(user_id + completion_date)+ 时间分区(按天分区)+ 星型数据模型(事实表+维度表关联),通过索引加速列扫描、分区减少数据扫描范围、模型优化减少关联复杂度,显著提升查询效率。
2) 【原理/概念讲解】
老师口吻解释核心概念:
course_completion_fact)存储核心行为数据(用户ID、课程ID、完成时间等),维度表(用户、课程)存储描述性属性。事实表按维度表主键(如user_id、course_id)建立索引,查询时通过外键连接,索引加速关联。3) 【对比与适用场景】
| 优化方案 | 定义 | 特性 | 适用场景 | 注意点 |
|---|---|---|---|---|
| 复合索引 | 多列组合的B+树索引 | 提升多列组合查询效率,减少I/O | 查询条件包含多个列(如user_id和date) | 索引列顺序影响效率,需按查询条件顺序排列 |
| 时间分区 | 按时间维度(如天、月)划分数据 | 减少查询扫描范围,按时间范围过滤 | 时间序列查询(如近30天、近一年) | 分区粒度需平衡查询粒度和管理成本 |
| 星型模式 | 事实表+维度表结构 | 事实表存储行为,维度表存储属性,减少关联复杂度 | 多维分析查询(如用户完成率、课程效果) | 维度表需建立主键索引,事实表按维度表主键关联 |
4) 【示例】
假设事实表course_completion_fact结构:
user_id (INT, PK)course_id (INT, FK)completion_date (DATE, 分区列)is_completed (BOOLEAN)维度表user_dim:
user_id (INT, PK)user_name (VARCHAR)user_level (INT)维度表course_dim:
course_id (INT, PK)course_name (VARCHAR)course_type (INT)查询优化后SQL(伪代码):
SELECT
u.user_name,
c.course_name,
COUNT(f.is_completed) AS completed_count,
COUNT(*) AS total_count,
(COUNT(f.is_completed) * 1.0 / COUNT(*)) AS completion_rate
FROM
course_completion_fact f
JOIN
user_dim u ON f.user_id = u.user_id
JOIN
course_dim c ON f.course_id = c.course_id
WHERE
f.user_id = ? -- 用户ID
AND f.completion_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 30 DAY) AND CURDATE()
GROUP BY
u.user_name, c.course_name;
优化点:
course_completion_fact建立复合索引:CREATE INDEX idx_user_date ON course_completion_fact(user_id, completion_date);completion_date分区:CREATE TABLE course_completion_fact (user_id INT, course_id INT, completion_date DATE, is_completed BOOLEAN) PARTITION BY RANGE (completion_date) (PARTITION p0 VALUES LESS THAN ('2023-01-01'), PARTITION p1 VALUES LESS THAN ('2023-02-01'), ...);CREATE INDEX idx_user_id ON user_dim(user_id); CREATE INDEX idx_course_id ON course_dim(course_id);5) 【面试口播版答案】
(约80秒)
“面试官您好,针对按用户ID查询近30天课程完成率的场景,核心优化思路是结合复合索引、时间分区、星型数据模型,具体来说:
首先,在事实表(如课程完成事实表)上建立复合索引(user_id + completion_date),查询时系统先按用户ID定位数据,再按日期过滤,避免全表扫描;
其次,对事实表按completion_date进行时间分区(按天分区),查询近30天时只需扫描最近30个分区,大幅减少数据量;
再者,采用星型模式,事实表存储核心行为数据(用户ID、课程ID、完成时间等),维度表(用户、课程)存储描述性属性,维度表按主键建立索引,查询时通过外键连接,索引加速关联。
这样,查询效率会显著提升,因为索引减少了I/O,分区减少了扫描范围,模型优化减少了关联复杂度。总结来说,通过复合索引+时间分区+星型模式,可以高效处理按用户ID和日期范围查询的课程完成率。”
6) 【追问清单】
user_id和completion_date两个列,复合索引能同时利用这两个列的排序,提升多列组合查询效率。user_id、course_id)与维度表关联,查询时通过外键连接,索引加速关联,减少全表扫描。7) 【常见坑/雷区】
user_id,忽略completion_date,导致查询时仍需扫描全表,索引失效。