tb_vehicle_gps_segment_mileage✅ 查询性能提升: 通过分区裁剪,查询只扫描相关分区,性能提升50%-80%
✅ 维护简化: 按月分区,可以快速删除或归档历史数据
✅ 存储优化: 便于数据归档,释放磁盘空间
✅ 并发优化: 不同分区可以并行操作,减少锁冲突
segment_start_time(时间段开始时间)2024年: p202401, p202402, ..., p202412 (12个分区)
2025年: p202501, p202502, ..., p202512 (12个分区)
2026年: p202601, p202602, ..., p202612 (12个分区)
未来: pfuture (容纳所有未来数据)
⚠️ 重要: 分区表的主键和唯一键必须包含分区键
原表结构:sql PRIMARY KEY (`segment_id`), UNIQUE KEY `uk_vehicle_time` (`vehicle_id`, `segment_start_time`)
新表结构:sql PRIMARY KEY (`segment_id`, `segment_start_time`), -- 主键包含分区键 UNIQUE KEY `uk_vehicle_time` (`vehicle_id`, `segment_start_time`) -- 已包含分区键
# 备份整个数据库
mysqldump -u用户名 -p 数据库名 > backup_$(date +%Y%m%d).sql
# 或只备份单表
mysqldump -u用户名 -p 数据库名 tb_vehicle_gps_segment_mileage > backup_segment_mileage_$(date +%Y%m%d).sql
-- 查看总记录数
SELECT COUNT(*) as total_records FROM tb_vehicle_gps_segment_mileage;
-- 查看按月分布
SELECT
DATE_FORMAT(segment_start_time, '%Y-%m') as month,
COUNT(*) as record_count,
ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM tb_vehicle_gps_segment_mileage), 2) as percentage
FROM tb_vehicle_gps_segment_mileage
GROUP BY DATE_FORMAT(segment_start_time, '%Y-%m')
ORDER BY month;
-- 查看表大小
SELECT
TABLE_NAME,
ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS size_mb,
TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage';
-- 在业务低峰期执行 partition_vehicle_gps_segment_mileage.sql
source d:/project/急救转运/code/Api/RuoYi-Vue-master/sql/partition_vehicle_gps_segment_mileage.sql
或分步执行:
1. 创建新分区表(tb_vehicle_gps_segment_mileage_new)
2. 分批迁移数据
3. 验证数据一致性
4. 切换表名
测试以下功能是否正常:
- ✅ GPS里程计算任务
- ✅ 车辆里程查询
- ✅ 任务里程统计
- ✅ 里程报表
-- 确认运行正常后,可以删除备份表(建议保留1-2周)
DROP TABLE tb_vehicle_gps_segment_mileage_backup;
-- 手动添加2027年2月分区
ALTER TABLE tb_vehicle_gps_segment_mileage
REORGANIZE PARTITION pfuture INTO (
PARTITION p202702 VALUES LESS THAN (TO_DAYS('2027-03-01')),
PARTITION pfuture VALUES LESS THAN MAXVALUE
);
-- 或使用存储过程自动添加
CALL add_gps_segment_partition();
-- 方式1: 直接删除分区(数据不可恢复)
ALTER TABLE tb_vehicle_gps_segment_mileage DROP PARTITION p202401;
-- 方式2: 归档后删除
-- 先导出数据到归档表
CREATE TABLE tb_vehicle_gps_segment_mileage_archive_202401
SELECT * FROM tb_vehicle_gps_segment_mileage PARTITION(p202401);
-- 然后删除分区
ALTER TABLE tb_vehicle_gps_segment_mileage DROP PARTITION p202401;
-- 查看所有分区信息
SELECT * FROM v_gps_segment_partition_stats;
-- 或直接查询
SELECT
PARTITION_NAME as '分区名',
TABLE_ROWS as '记录数',
ROUND(DATA_LENGTH/1024/1024, 2) as '数据(MB)',
ROUND(INDEX_LENGTH/1024/1024, 2) as '索引(MB)'
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'tb_vehicle_gps_segment_mileage'
ORDER BY PARTITION_ORDINAL_POSITION;
-- 分析表(更新统计信息)
ANALYZE TABLE tb_vehicle_gps_segment_mileage;
-- 优化表(回收碎片空间)
OPTIMIZE TABLE tb_vehicle_gps_segment_mileage;
-- 示例1: 带时间范围的查询
SELECT * FROM tb_vehicle_gps_segment_mileage
WHERE segment_start_time >= '2025-01-01'
AND segment_start_time < '2025-02-01'
AND vehicle_id = 123;
-- 示例2: 按月统计
SELECT
DATE_FORMAT(segment_start_time, '%Y-%m') as month,
SUM(segment_distance) as total_distance
FROM tb_vehicle_gps_segment_mileage
WHERE segment_start_time >= '2025-01-01'
AND segment_start_time < '2025-12-31'
GROUP BY DATE_FORMAT(segment_start_time, '%Y-%m');
-- 缺少时间条件,会扫描所有分区
SELECT * FROM tb_vehicle_gps_segment_mileage
WHERE vehicle_id = 123;
-- 应该改为:
SELECT * FROM tb_vehicle_gps_segment_mileage
WHERE vehicle_id = 123
AND segment_start_time >= DATE_SUB(NOW(), INTERVAL 30 DAY);
# 每月1号凌晨1点自动添加新分区
0 1 1 * * mysql -u用户名 -p密码 数据库名 -e "CALL add_gps_segment_partition();"
# 每季度删除12个月之前的历史分区
0 2 1 1,4,7,10 * /path/to/cleanup_old_partitions.sh
如果分区后出现问题,可以快速回滚:
-- 1. 停止应用写入
-- 2. 恢复原表
RENAME TABLE tb_vehicle_gps_segment_mileage TO tb_vehicle_gps_segment_mileage_failed;
RENAME TABLE tb_vehicle_gps_segment_mileage_backup TO tb_vehicle_gps_segment_mileage;
-- 3. 同步切换期间的新数据(如果有)
INSERT INTO tb_vehicle_gps_segment_mileage
SELECT * FROM tb_vehicle_gps_segment_mileage_failed
WHERE create_time > (SELECT MAX(create_time) FROM tb_vehicle_gps_segment_mileage);
-- 4. 重启应用
A: 不会。分区对应用透明,SQL语句不需要修改。
A: MySQL 5.7+ 可以在线转换,但建议在低峰期执行,大表可能需要较长时间。
A: 可以,使用 ALTER TABLE ... REMOVE PARTITIONING;
A: 是的,这是MySQL分区表的限制。
A: 根据业务需求和存储容量,建议保留12-24个月,更早的数据归档到冷存储。
如果执行过程中遇到问题,请:
1. 检查错误日志: /var/log/mysql/error.log
2. 查看慢查询日志,对比性能
3. 确保有完整备份
4. 必要时联系DBA或技术支持
最后提醒:
⚠️ 执行前务必备份!
⚠️ 选择业务低峰期执行!
⚠️ 准备好回滚方案!