409 lines
10 KiB
Markdown
409 lines
10 KiB
Markdown
# 数据模型统一重构执行指南
|
||
|
||
## 概述
|
||
|
||
本指南详细说明如何安全地执行数据模型统一重构,将两个项目的数据模型统一为:
|
||
- **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接口正常响应
|
||
- [ ] 前端页面正常显示
|
||
|
||
### 功能层面
|
||
- [ ] 车辆管理功能正常
|
||
- [ ] 实时位置监控正常
|
||
- [ ] 轨迹查询正常
|
||
- [ ] 报表生成正常
|
||
- [ ] 数据关联查询正常
|
||
|
||
### 性能层面
|
||
- [ ] 查询性能不降低
|
||
- [ ] 索引使用率正常
|
||
- [ ] 内存使用正常
|
||
- [ ] 并发性能正常
|
||
|
||
---
|
||
|
||
**执行建议**: 建议在测试环境先完整执行一遍,确保所有步骤都能正常工作后,再在生产环境执行。 |