
1) 【一句话结论】
采用分库分表(水平分区)结合时间分区策略,通过自增主键+复合索引优化查询,结合写入缓冲(如MySQL binlog缓冲)和定期归档,平衡高并发写入、查询性能与长期存储需求。
2) 【原理/概念讲解】
INSERT ... VALUES多条语句),减少网络开销;可配置写入缓冲(如MySQL的binlog缓冲或事务队列),降低写入延迟。类比:流水线作业,批量处理比单条处理效率高,减少排队时间。user_id和trade_date,可快速定位。3) 【对比与适用场景】
| 策略/组件 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 水平分区(分库分表) | 按业务或数据量切分表到多个数据库实例 | 提高并发写入能力,隔离数据 | 大规模交易数据,需分布式存储 | 需跨库查询,需分布式事务支持(如两阶段提交) |
| 时间分区(按日期分区) | 按时间范围(如日、月、年)切分表 | 便于归档和查询历史数据 | 长期存储,减少主表数据量 | 分区键选择(如trade_date),避免频繁分区操作 |
| 复合索引 | 多列组合的索引 | 覆盖查询条件,减少回表 | 查询涉及多列(如时间+类型+金额) | 索引列顺序影响效率,前缀列应按查询频率排序 |
| 写入缓冲 | 临时缓存写入请求(如MySQL binlog缓冲) | 减少写入延迟,提高吞吐 | 高并发写入场景 | 需设置合理缓冲大小,避免内存溢出 |
4) 【示例】
-- 表结构
CREATE TABLE trade_log (
trade_id BIGINT AUTO_INCREMENT PRIMARY KEY, -- 自增主键,高并发下无冲突
trade_time TIMESTAMP NOT NULL, -- 交易时间,精确到秒
user_id BIGINT NOT NULL, -- 用户ID
trade_type VARCHAR(20) NOT NULL, -- 交易类型(如买入、卖出)
amount DECIMAL(18,2) NOT NULL, -- 交易金额
status VARCHAR(10) DEFAULT 'completed', -- 交易状态
INDEX idx_trade_time_user (trade_time, user_id), -- 复合索引,覆盖查询常用字段
INDEX idx_trade_type_amount (trade_type, amount) -- 另一个复合索引,支持按类型和金额查询
) ENGINE=InnoDB;
-- 时间分区(按交易日期分区)
ALTER TABLE trade_log
PARTITION BY RANGE (TO_DAYS(trade_time)) (
PARTITION p202401 VALUES LESS THAN (TO_DAYS('2024-02-01')),
PARTITION p202402 VALUES LESS THAN (TO_DAYS('2024-03-01')),
PARTITION p202403 VALUES LESS THAN (TO_DAYS('2024-04-01')),
PARTITION pmax VALUES LESS THAN MAXVALUE -- 存放最新数据
);
(注:示例中分区按交易日期,每日一个分区,便于按日查询和归档)
5) 【面试口播版答案】
“面试官您好,针对每日交易流水的高并发写入、查询和长期存储需求,我的设计思路是:首先,表结构上采用自增主键(保证唯一性,支持高并发写入),并设置复合索引(如trade_time+user_id、trade_type+amount),覆盖常用查询条件,减少回表I/O。然后,采用时间分区(按交易日期分区),将每日数据切分为独立分区,既便于按日查询,又能通过定期归档(如将老分区转储为归档文件)减少主表压力。对于高并发写入,支持批量插入(如INSERT ... VALUES多条语句),并配置写入缓冲(如MySQL的binlog缓冲),降低写入延迟。查询时,通过索引覆盖,快速定位数据,提升性能。长期存储方面,分区表按时间划分,历史数据归档后,主表保持最新数据,兼顾查询和存储效率。总结来说,通过分区+索引+批量写入的组合,平衡了高并发、查询性能和长期存储需求。”
6) 【追问清单】
trade_date是否合理?7) 【常见坑/雷区】