# 数据模型统一重构执行指南

## 概述

本指南详细说明如何安全地执行数据模型统一重构，将两个项目的数据模型统一为：
- **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为数字ID，license_plate为车牌号
- 消除所有字段名不一致问题
- 重构所有业务视图和索引
- 优化数据库性能
EOF
```

## 🎯 完成检查清单

### 数据库层面
- [ ] 所有表的vehicle_id都是BIGINT类型
- [ ] 所有表的车牌号字段都叫license_plate
- [ ] 所有业务视图正常工作
- [ ] 所有索引创建成功
- [ ] 数据完整性验证通过

### 应用层面
- [ ] Java实体类已更新
- [ ] MyBatis映射已更新
- [ ] Service层代码已更新
- [ ] API接口正常响应
- [ ] 前端页面正常显示

### 功能层面
- [ ] 车辆管理功能正常
- [ ] 实时位置监控正常
- [ ] 轨迹查询正常
- [ ] 报表生成正常
- [ ] 数据关联查询正常

### 性能层面
- [ ] 查询性能不降低
- [ ] 索引使用率正常
- [ ] 内存使用正常
- [ ] 并发性能正常

---

**执行建议**: 建议在测试环境先完整执行一遍，确保所有步骤都能正常工作后，再在生产环境执行。 