QDAirPortBackend0122/doc/work/数据模型统一重构执行指南_20250115.md
2026-01-22 13:19:47 +08:00

409 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 数据模型统一重构执行指南
## 概述
本指南详细说明如何安全地执行数据模型统一重构,将两个项目的数据模型统一为:
- **vehicle_id**: 所有表中统一为 `BIGINT` 数字ID
- **license_plate**: 所有表中统一为 `VARCHAR(50)` 车牌号字段名
## ⚠️ 重要提醒
### 风险评估
- **高风险操作**: 涉及大量表结构变更和数据迁移
- **停机需求**: 建议在维护窗口期间执行
- **数据备份**: 执行前必须进行完整备份
### 前置条件
- [ ] 数据库连接正常
- [ ] 有足够的磁盘空间建议预留当前数据量的50%
- [ ] 数据库用户有DDL权限
- [ ] 已停止所有相关应用服务
## 📋 执行步骤
### 第一阶段:准备工作
#### 1. 环境检查
```bash
# 检查数据库连接
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. 数据备份
```bash
# 完整备份
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. 停止相关服务
```bash
# 停止QAUP-Management服务
# 停止CollisionAvoidanceSystem服务
# 验证服务已停止
ps aux | grep -E "(qaup|collision)"
```
### 第二阶段:数据预检查
#### 1. 检查数据完整性
```sql
-- 检查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. 检查字段约束
```sql
-- 检查车牌号格式
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. 预估执行时间
```sql
-- 预估数据量
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. 执行重构脚本
```bash
# 执行主要重构脚本
psql -h localhost -U postgres -d qaup -f sql/data_model_unification.sql
# 检查执行结果
echo $? # 应该返回0表示成功
```
#### 3. 监控执行过程
```sql
-- 在另一个终端中监控进度
-- 查看当前活动会话
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. 表结构验证
```sql
-- 验证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. 数据完整性验证
```sql
-- 检查数据量是否一致
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. 业务视图验证
```sql
-- 测试业务视图
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. 关联查询验证
```sql
-- 测试车辆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. 重启服务
```bash
# 启动QAUP-Management服务
# 启动CollisionAvoidanceSystem服务
# 检查服务状态
ps aux | grep -E "(qaup|collision)"
```
#### 2. 功能验证
- [ ] 车辆信息管理功能
- [ ] 实时位置监控功能
- [ ] 轨迹查询功能
- [ ] 报表生成功能
- [ ] API接口调用
#### 3. 性能验证
```sql
-- 测试查询性能
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');
```
## 🔄 回滚处理
### 什么时候需要回滚
- 重构过程中出现错误
- 数据验证发现问题
- 应用层功能异常
- 性能严重下降
### 回滚步骤
```bash
# 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
```
## 📊 监控和维护
### 性能监控
```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;
```
### 定期维护
```sql
-- 定期更新统计信息
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接口的字段名称
- 检查前端组件的字段绑定
## 📈 版本管理
### 更新版本信息
```bash
# 更新VERSION.md
echo "0.1.4" > VERSION.md
# 更新changelog.md
cat >> changelog.md << EOF
## [0.1.4] - $(date +%Y-%m-%d)
### 重构
- 统一数据模型vehicle_id为数字IDlicense_plate为车牌号
- 消除所有字段名不一致问题
- 重构所有业务视图和索引
- 优化数据库性能
EOF
```
## 🎯 完成检查清单
### 数据库层面
- [ ] 所有表的vehicle_id都是BIGINT类型
- [ ] 所有表的车牌号字段都叫license_plate
- [ ] 所有业务视图正常工作
- [ ] 所有索引创建成功
- [ ] 数据完整性验证通过
### 应用层面
- [ ] Java实体类已更新
- [ ] MyBatis映射已更新
- [ ] Service层代码已更新
- [ ] API接口正常响应
- [ ] 前端页面正常显示
### 功能层面
- [ ] 车辆管理功能正常
- [ ] 实时位置监控正常
- [ ] 轨迹查询正常
- [ ] 报表生成正常
- [ ] 数据关联查询正常
### 性能层面
- [ ] 查询性能不降低
- [ ] 索引使用率正常
- [ ] 内存使用正常
- [ ] 并发性能正常
---
**执行建议**: 建议在测试环境先完整执行一遍,确保所有步骤都能正常工作后,再在生产环境执行。