
1) 【一句话结论】
采用时间范围分区表(按申请时间天分区)配合覆盖索引(含申请时间+用户ID等查询字段),通过分区裁剪与索引覆盖优化查询效率,支撑每天10万条数据的快速时间范围查询。
2) 【原理/概念讲解】
3) 【对比与适用场景】
| 对比项 | 范围分区(本题适用) | 列表分区 | 普通索引 | 覆盖索引 |
|---|---|---|---|---|
| 定义 | 按连续/离散范围值(如时间)划分 | 按离散值(如地区、状态)划分 | 仅存储索引键值+数据行指针 | 索引包含查询所需所有字段 |
| 特性 | 适合时间序列数据,查询时定位分区 | 适合离散值查询 | 需回表获取数据 | 无需回表,直接索引取值 |
| 使用场景 | 日志、时间序列数据(本题教育贷款申请表按申请时间分区) | 按地区/状态查询 | 非覆盖查询,或字段不在索引中 | 时间范围+多字段查询(如本题) |
| 注意点 | 分区键需与查询条件高度相关(如时间分区) | 分区值需覆盖查询条件 | 不能直接用于覆盖查询 | 索引大小增加,插入时需更新索引 |
4) 【示例】
CREATE TABLE education_loan_applications (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
application_time TIMESTAMP NOT NULL,
loan_amount DECIMAL(10,2),
status VARCHAR(20),
INDEX idx_user_time (user_id, application_time),
INDEX idx_time_cover (application_time, user_id, loan_amount) -- 覆盖索引
) PARTITION BY RANGE (TO_DAYS(application_time)) (
PARTITION p202401 VALUES LESS THAN (TO_DAYS('20240201')),
PARTITION p202402 VALUES LESS THAN (TO_DAYS('20240301')),
PARTITION p202403 VALUES LESS THAN (TO_DAYS('20240401')),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
SELECT user_id, COUNT(*) as active_users
FROM education_loan_applications
WHERE application_time BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY user_id;
p202401分区(按申请时间范围定位分区);idx_time_cover包含application_time、user_id、loan_amount,查询时直接从索引获取数据,无需回表。5) 【面试口播版答案】
“面试官您好,针对教育贷款申请表每天10万条数据,按申请时间范围查询活跃用户的需求,我的设计思路是:首先采用时间范围分区表,按申请时间的天进行范围分区,这样查询时只需扫描对应时间分区,减少数据扫描量;然后设计覆盖索引,包含申请时间和用户ID等查询字段,实现查询时直接从索引获取数据,避免回表;最后通过分区裁剪和索引覆盖优化查询效率,支撑高并发查询。具体来说,表结构会按申请时间分区,索引包含时间字段和用户ID,查询时只扫描相关分区并利用覆盖索引快速返回结果。”
6) 【追问清单】
| 追问问题 | 回答要点 |
|---|---|
| 分区粒度如何选择? | 分区粒度需平衡分区数量(太多分区增加管理成本)和查询效率(太少分区导致扫描范围大),本题按天分区是常见选择,兼顾性能和管理。 |
| 并发写入时分区如何处理? | 使用分区键自动分区(如申请时间),避免手动分区,减少并发写入时的分区冲突;同时考虑分区合并策略,当分区数据量过大时合并分区。 |
| 数据量增长后如何调整? | 定期合并旧分区(如按月合并),减少分区数量;优化索引结构,如增加复合索引字段,提升查询覆盖度。 |
| 如果查询条件包含多个字段(如时间+状态)怎么办? | 扩展覆盖索引,包含所有查询字段;或使用多列索引,确保查询条件字段在索引中连续出现。 |
| 分区键选择是否会影响查询性能? | 分区键应与查询条件高度相关(如时间范围查询用时间分区键),否则会导致全表扫描,需根据查询模式调整分区键。 |
7) 【常见坑/雷区】