
采用按事件时间(天)分区的日志表,通过覆盖索引优化查询性能,结合分布式事务(并考虑最终一致性替代方案),同时设计分区合并策略应对数据量增长,保证数据一致性与扩展性。
用户行为日志属于时序数据,数据量大且查询频繁(如按用户ID、时间范围、操作类型筛选)。核心设计逻辑如下:
event_time)的日期字段分区(如按天),将数据分散到不同分区。类比“时序数据像流水账,按日期装订账本,找某天记录只翻对应日期的账本,避免全盘查找”,便于管理旧数据(如删除30天前的分区)并提升查询效率。user_id, event_time, event_id)保证唯一性,同时构建覆盖索引(如(user_id, event_time)、(event_type, event_time)),直接支持查询条件,减少I/O。覆盖索引包含所有查询所需列,避免回表。| 分区策略 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 按天分区 | 按event_time的日期字段分区 | 数据按天分散,分区数量适中,便于清理旧数据(如保留30天),查询时只扫描当前分区 | 日志数据量大,查询时间范围频繁(如日活跃分析) | 需定期维护分区(如删除过期分区),分区数量适中 |
| 按小时分区 | 按event_time的小时字段分区 | 分区粒度更细,适合小时级时间范围查询(如实时用户行为监控) | 需要小时级分析(如实时用户活跃度) | 分区数量多,查询时可能扫描更多分区,存储成本高 |
| 按月分区 | 按event_time的月份字段分区 | 分区粒度更大,适合长期历史数据分析(如年度趋势) | 需长期存储历史数据(如市场分析) | 分区数量少,但查询时可能扫描多个月份分区,性能受影响 |
CREATE TABLE user_behavior_log (
user_id BIGINT NOT NULL,
event_type VARCHAR(20) NOT NULL, -- 如 'click', 'purchase'
event_time TIMESTAMP NOT NULL,
event_data JSON, -- 事件具体数据(如点击的页面ID)
PRIMARY KEY (user_id, event_time, event_id),
INDEX idx_user_time (user_id, event_time), -- 覆盖索引,支持按用户ID+时间范围查询
INDEX idx_event_type_time (event_type, event_time) -- 支持按操作类型+时间范围查询
) PARTITIONED BY (day DATE) -- 按事件时间的日期分区
SELECT * FROM user_behavior_log
WHERE user_id = 12345 AND event_time BETWEEN '2023-10-01 00:00:00' AND '2023-10-31 23:59:59';
“面试官您好,针对用户行为日志的存储,我会设计一个按事件时间(天)分区的表结构。首先,表包含user_id、event_type、event_time、event_data等字段,主键是复合键(user_id, event_time, event_id)保证唯一性。然后,索引方面,构建覆盖索引(user_id, event_time)和(event_type, event_time),直接支持按用户ID、时间范围、操作类型的查询。分区策略按事件时间的日期分区,每天一个分区,这样数据增长时可以管理旧数据(如删除30天前的分区),查询时只扫描当前分区,提升性能。数据一致性通过分布式事务(两阶段提交协议)保证,但考虑到2PC的阻塞问题,也会采用最终一致性方案,比如异步写入日志,通过补偿事务确保一致性。当数据量增长时,分区会自动扩展,旧分区可以按月合并,减少分区数量,同时优化查询时只扫描相关分区,保持系统高效。”
event_type列的哈希索引)。