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

10 KiB
Raw Blame History

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

概述

本指南详细说明如何安全地执行数据模型统一重构,将两个项目的数据模型统一为:

  • 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为数字IDlicense_plate为车牌号
- 消除所有字段名不一致问题
- 重构所有业务视图和索引
- 优化数据库性能
EOF

🎯 完成检查清单

数据库层面

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

应用层面

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

功能层面

  • 车辆管理功能正常
  • 实时位置监控正常
  • 轨迹查询正常
  • 报表生成正常
  • 数据关联查询正常

性能层面

  • 查询性能不降低
  • 索引使用率正常
  • 内存使用正常
  • 并发性能正常

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