10 KiB
10 KiB
数据模型统一重构执行指南
概述
本指南详细说明如何安全地执行数据模型统一重构,将两个项目的数据模型统一为:
- vehicle_id: 所有表中统一为
BIGINT数字ID - license_plate: 所有表中统一为
VARCHAR(50)车牌号字段名
⚠️ 重要提醒
风险评估
- 高风险操作: 涉及大量表结构变更和数据迁移
- 停机需求: 建议在维护窗口期间执行
- 数据备份: 执行前必须进行完整备份
前置条件
- 数据库连接正常
- 有足够的磁盘空间(建议预留当前数据量的50%)
- 数据库用户有DDL权限
- 已停止所有相关应用服务
📋 执行步骤
第一阶段:准备工作
1. 环境检查
# 检查数据库连接
psql -h localhost -U postgres -d qaup -c "SELECT version();"
# 检查表是否存在
psql -h localhost -U postgres -d qaup -c "
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name IN ('sys_vehicle_info', 'vehicle_locations', 'vehicle_trajectories', 'vehicle_commands', 'rule_violation_events');
"
2. 数据备份
# 完整备份
pg_dump -h localhost -U postgres -d qaup > backup_before_unification_$(date +%Y%m%d_%H%M%S).sql
# 验证备份文件
ls -lh backup_before_unification_*.sql
3. 停止相关服务
# 停止QAUP-Management服务
# 停止CollisionAvoidanceSystem服务
# 验证服务已停止
ps aux | grep -E "(qaup|collision)"
第二阶段:数据预检查
1. 检查数据完整性
-- 检查sys_vehicle_info表
SELECT COUNT(*) as total_vehicles,
COUNT(DISTINCT license_plate_number) as unique_plates,
COUNT(CASE WHEN license_plate_number IS NULL THEN 1 END) as null_plates
FROM sys_vehicle_info;
-- 检查vehicle_locations表
SELECT COUNT(*) as total_locations,
COUNT(DISTINCT vehicle_id) as unique_vehicles,
COUNT(CASE WHEN vehicle_id IS NULL THEN 1 END) as null_ids
FROM vehicle_locations;
-- 检查是否有重复车牌号
SELECT license_plate_number, COUNT(*)
FROM sys_vehicle_info
GROUP BY license_plate_number
HAVING COUNT(*) > 1;
2. 检查字段约束
-- 检查车牌号格式
SELECT DISTINCT license_plate_number
FROM sys_vehicle_info
WHERE license_plate_number IS NULL
OR length(license_plate_number) = 0
OR length(license_plate_number) > 50;
-- 检查vehicle_locations中的vehicle_id
SELECT DISTINCT vehicle_id
FROM vehicle_locations
WHERE vehicle_id IS NULL
OR length(vehicle_id) = 0
OR length(vehicle_id) > 50;
第三阶段:执行重构
1. 预估执行时间
-- 预估数据量
SELECT
'sys_vehicle_info' as table_name, COUNT(*) as record_count
FROM sys_vehicle_info
UNION ALL
SELECT
'vehicle_locations' as table_name, COUNT(*) as record_count
FROM vehicle_locations
UNION ALL
SELECT
'vehicle_trajectories' as table_name, COUNT(*) as record_count
FROM vehicle_trajectories
UNION ALL
SELECT
'vehicle_commands' as table_name, COUNT(*) as record_count
FROM vehicle_commands
UNION ALL
SELECT
'rule_violation_events' as table_name, COUNT(*) as record_count
FROM rule_violation_events;
预估时间参考:
- 小型数据库(< 10万条记录):5-10分钟
- 中型数据库(10万-100万条记录):10-30分钟
- 大型数据库(> 100万条记录):30分钟-2小时
2. 执行重构脚本
# 执行主要重构脚本
psql -h localhost -U postgres -d qaup -f sql/data_model_unification.sql
# 检查执行结果
echo $? # 应该返回0表示成功
3. 监控执行过程
-- 在另一个终端中监控进度
-- 查看当前活动会话
SELECT pid, state, query FROM pg_stat_activity WHERE datname = 'qaup';
-- 查看锁状态
SELECT * FROM pg_locks WHERE database = (SELECT oid FROM pg_database WHERE datname = 'qaup');
第四阶段:验证结果
1. 表结构验证
-- 验证sys_vehicle_info表结构
\d sys_vehicle_info
-- 验证vehicle_locations表结构
\d vehicle_locations
-- 验证vehicle_trajectories表结构
\d vehicle_trajectories
-- 验证vehicle_commands表结构
\d vehicle_commands
-- 验证rule_violation_events表结构
\d rule_violation_events
2. 数据完整性验证
-- 检查数据量是否一致
SELECT
'sys_vehicle_info' as table_name, COUNT(*) as record_count
FROM sys_vehicle_info
UNION ALL
SELECT
'vehicle_locations' as table_name, COUNT(*) as record_count
FROM vehicle_locations
UNION ALL
SELECT
'vehicle_trajectories' as table_name, COUNT(*) as record_count
FROM vehicle_trajectories
UNION ALL
SELECT
'vehicle_commands' as table_name, COUNT(*) as record_count
FROM vehicle_commands
UNION ALL
SELECT
'rule_violation_events' as table_name, COUNT(*) as record_count
FROM rule_violation_events;
-- 检查字段统一性
SELECT
'sys_vehicle_info' as table_name,
COUNT(*) as total_records,
COUNT(vehicle_id) as has_vehicle_id,
COUNT(license_plate) as has_license_plate
FROM sys_vehicle_info
UNION ALL
SELECT
'vehicle_locations' as table_name,
COUNT(*) as total_records,
COUNT(vehicle_id) as has_vehicle_id,
COUNT(license_plate) as has_license_plate
FROM vehicle_locations
UNION ALL
SELECT
'vehicle_trajectories' as table_name,
COUNT(*) as total_records,
COUNT(vehicle_id) as has_vehicle_id,
COUNT(license_plate) as has_license_plate
FROM vehicle_trajectories
UNION ALL
SELECT
'vehicle_commands' as table_name,
COUNT(*) as total_records,
COUNT(vehicle_id) as has_vehicle_id,
COUNT(license_plate) as has_license_plate
FROM vehicle_commands;
3. 业务视图验证
-- 测试业务视图
SELECT * FROM vehicle_complete_info LIMIT 5;
SELECT * FROM vehicle_status_summary LIMIT 5;
SELECT * FROM vehicle_info_with_location LIMIT 5;
SELECT * FROM vehicle_trajectory_view LIMIT 5;
4. 关联查询验证
-- 测试车辆ID关联
SELECT
vi.vehicle_id,
vi.license_plate,
vl.vehicle_id as location_vehicle_id,
vl.license_plate as location_license_plate
FROM sys_vehicle_info vi
LEFT JOIN vehicle_locations vl ON vi.vehicle_id = vl.vehicle_id
LIMIT 10;
-- 测试车牌号关联
SELECT
vi.license_plate,
COUNT(vl.id) as location_count
FROM sys_vehicle_info vi
LEFT JOIN vehicle_locations vl ON vi.license_plate = vl.license_plate
GROUP BY vi.license_plate
LIMIT 10;
第五阶段:应用层验证
1. 重启服务
# 启动QAUP-Management服务
# 启动CollisionAvoidanceSystem服务
# 检查服务状态
ps aux | grep -E "(qaup|collision)"
2. 功能验证
- 车辆信息管理功能
- 实时位置监控功能
- 轨迹查询功能
- 报表生成功能
- API接口调用
3. 性能验证
-- 测试查询性能
EXPLAIN ANALYZE SELECT * FROM vehicle_info_with_location WHERE license_plate = '京A12345';
-- 测试索引使用情况
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read
FROM pg_stat_user_indexes
WHERE tablename IN ('sys_vehicle_info', 'vehicle_locations', 'vehicle_trajectories', 'vehicle_commands');
🔄 回滚处理
什么时候需要回滚
- 重构过程中出现错误
- 数据验证发现问题
- 应用层功能异常
- 性能严重下降
回滚步骤
# 1. 停止所有服务
# 2. 执行回滚脚本
psql -h localhost -U postgres -d qaup -f sql/data_model_unification_rollback.sql
# 3. 验证回滚结果
psql -h localhost -U postgres -d qaup -c "
SELECT
column_name, data_type
FROM information_schema.columns
WHERE table_name = 'sys_vehicle_info'
AND column_name LIKE '%license%';
"
# 4. 恢复数据备份(如果必要)
# psql -h localhost -U postgres -d qaup < backup_before_unification_YYYYMMDD_HHMMSS.sql
📊 监控和维护
性能监控
-- 监控查询性能
SELECT
schemaname, tablename,
seq_scan, seq_tup_read,
idx_scan, idx_tup_fetch
FROM pg_stat_user_tables
WHERE tablename IN ('sys_vehicle_info', 'vehicle_locations', 'vehicle_trajectories', 'vehicle_commands')
ORDER BY seq_tup_read DESC;
定期维护
-- 定期更新统计信息
ANALYZE sys_vehicle_info;
ANALYZE vehicle_locations;
ANALYZE vehicle_trajectories;
ANALYZE vehicle_commands;
ANALYZE rule_violation_events;
-- 定期清理和重建索引
REINDEX TABLE sys_vehicle_info;
REINDEX TABLE vehicle_locations;
REINDEX TABLE vehicle_trajectories;
REINDEX TABLE vehicle_commands;
REINDEX TABLE rule_violation_events;
📝 常见问题解答
Q1: 执行过程中断了怎么办?
- 检查错误日志
- 如果是网络问题,可以重新执行(脚本有幂等性)
- 如果是数据问题,执行回滚脚本
Q2: 数据量很大,执行时间太长怎么办?
- 考虑分批处理
- 在非业务高峰期执行
- 增加数据库配置参数(work_mem, maintenance_work_mem)
Q3: 外键约束导致失败怎么办?
- 脚本中外键约束是可选的
- 如果必须要外键,确保参照完整性
- 可以先删除外键,迁移后重新创建
Q4: 应用层报错怎么办?
- 检查Java代码中的字段映射
- 检查API接口的字段名称
- 检查前端组件的字段绑定
📈 版本管理
更新版本信息
# 更新VERSION.md
echo "0.1.4" > VERSION.md
# 更新changelog.md
cat >> changelog.md << EOF
## [0.1.4] - $(date +%Y-%m-%d)
### 重构
- 统一数据模型,vehicle_id为数字ID,license_plate为车牌号
- 消除所有字段名不一致问题
- 重构所有业务视图和索引
- 优化数据库性能
EOF
🎯 完成检查清单
数据库层面
- 所有表的vehicle_id都是BIGINT类型
- 所有表的车牌号字段都叫license_plate
- 所有业务视图正常工作
- 所有索引创建成功
- 数据完整性验证通过
应用层面
- Java实体类已更新
- MyBatis映射已更新
- Service层代码已更新
- API接口正常响应
- 前端页面正常显示
功能层面
- 车辆管理功能正常
- 实时位置监控正常
- 轨迹查询正常
- 报表生成正常
- 数据关联查询正常
性能层面
- 查询性能不降低
- 索引使用率正常
- 内存使用正常
- 并发性能正常
执行建议: 建议在测试环境先完整执行一遍,确保所有步骤都能正常工作后,再在生产环境执行。