5.8 KiB
5.8 KiB
车辆ID映射问题解决方案
问题描述
在数据库合并过程中发现了车辆标识符不一致的问题:
- QAUP-Management:
sys_vehicle_info.vehicle_id= 自增数字ID(主键) - CollisionAvoidanceSystem:
vehicle_locations.vehicle_id= 车牌号(字符串)
这导致两个系统的车辆数据无法正确关联。
解决方案对比
🥇 方案一:优化表结构(推荐)
特点:
- ✅ 保持数据完整性
- ✅ 支持双重关联方式
- ✅ 语义清晰,便于维护
- ⚠️ 需要修改表结构
实施:
# 执行修复脚本
psql -h localhost -U postgres -d qaup -f sql/fix_vehicle_id_mapping.sql
优势:
- 添加
license_plate字段明确语义 - 添加
sys_vehicle_id字段支持数字ID关联 - 更新所有相关视图使用正确的关联逻辑
- 提供数据同步函数
🥈 方案二:视图层解决(简单)
特点:
- ✅ 不修改表结构
- ✅ 实施简单快速
- ⚠️ 依赖视图查询,性能稍逊
- ⚠️ 需要确保车牌号唯一性
关联逻辑:
-- 通过车牌号关联
SELECT vi.*, vl.location, vl.speed
FROM sys_vehicle_info vi
LEFT JOIN vehicle_locations vl ON vl.vehicle_id = vi.license_plate_number;
🥉 方案三:应用层处理(灵活)
特点:
- ✅ 数据库保持原样
- ✅ 灵活的映射逻辑
- ⚠️ 增加应用复杂性
- ⚠️ 性能开销相对较大
实现方式:
- 在应用层维护车牌号到数字ID的映射关系
- 通过缓存提高查询性能
推荐方案详解
方案一实施后的效果
1. 表结构变化
-- vehicle_locations表新增字段
ALTER TABLE vehicle_locations ADD COLUMN license_plate VARCHAR(50); -- 车牌号
ALTER TABLE vehicle_locations ADD COLUMN sys_vehicle_id BIGINT; -- 系统车辆ID
2. 数据关联方式
-- 方式1:通过车牌号关联(主要方式)
SELECT * FROM vehicle_complete_info WHERE license_plate_number = '京A12345';
-- 方式2:通过数字ID关联(可选)
SELECT * FROM sys_vehicle_info vi
JOIN vehicle_locations vl ON vl.sys_vehicle_id = vi.vehicle_id;
3. 新增业务视图
vehicle_info_with_location:车辆信息与位置
SELECT sys_vehicle_id, vehicle_plate, brand, longitude, latitude, status
FROM vehicle_info_with_location
WHERE vehicle_plate = '京A12345';
vehicle_trajectory_view:车辆轨迹
SELECT vehicle_plate, trajectory_date, total_distance
FROM vehicle_trajectory_view
WHERE vehicle_plate = '京A12345';
执行步骤
立即执行(推荐)
-
备份数据(重要)
pg_dump -h localhost -U postgres -d qaup > backup_before_fix_$(date +%Y%m%d_%H%M%S).sql -
执行修复脚本
psql -h localhost -U postgres -d qaup -f sql/fix_vehicle_id_mapping.sql -
验证结果
-- 检查新字段 \d vehicle_locations -- 测试视图 SELECT * FROM vehicle_complete_info LIMIT 5; -- 检查数据同步 SELECT COUNT(*) as total, COUNT(license_plate) as has_plate FROM vehicle_locations;
如果选择其他方案
方案二:仅更新视图
-- 只更新现有视图的关联逻辑
DROP VIEW IF EXISTS vehicle_complete_info;
CREATE OR REPLACE VIEW vehicle_complete_info AS
SELECT vi.*, vl.location, vl.speed, vl.timestamp
FROM sys_vehicle_info vi
LEFT JOIN LATERAL (
SELECT * FROM vehicle_locations
WHERE vehicle_id = vi.license_plate_number
ORDER BY timestamp DESC LIMIT 1
) vl ON true;
方案三:应用层映射
// 在应用代码中处理映射
@Service
public class VehicleMappingService {
public String getPlateById(Long vehicleId) {
// 从sys_vehicle_info查询车牌号
}
public Long getIdByPlate(String licensePlate) {
// 从sys_vehicle_info查询车辆ID
}
}
使用建议
开发中的最佳实践
-
统一使用车牌号作为业务标识符
-- 推荐:使用车牌号查询 SELECT * FROM vehicle_info_with_location WHERE vehicle_plate = '京A12345'; -
数据插入时同时设置两个字段
INSERT INTO vehicle_locations (vehicle_id, license_plate, sys_vehicle_id, ...) VALUES ('京A12345', '京A12345', 1001, ...); -
定期执行数据同步
-- 如果有新的车辆信息录入,执行同步 SELECT update_sys_vehicle_id();
查询性能优化
-- 利用新建的索引
CREATE INDEX idx_vehicle_locations_license_plate ON vehicle_locations(license_plate);
CREATE INDEX idx_vehicle_locations_sys_vehicle_id ON vehicle_locations(sys_vehicle_id);
常见问题解答
Q1: 为什么推荐方案一?
- 数据完整性:支持严格的外键约束
- 查询性能:专用索引优化
- 语义清晰:字段名明确表达用途
- 向后兼容:保留原有的vehicle_id字段
Q2: 原有代码需要修改吗?
- CollisionAvoidanceSystem:不需要修改,继续使用vehicle_id字段
- QAUP-Management:建议使用新的视图进行查询
- 新功能开发:推荐使用license_plate字段
Q3: 如果车牌号有重复怎么办?
- 在sys_vehicle_info表上添加唯一约束:
ALTER TABLE sys_vehicle_info ADD CONSTRAINT uk_license_plate UNIQUE (license_plate_number);
Q4: 数据迁移会丢失吗?
- 不会,脚本使用ADD COLUMN IF NOT EXISTS确保安全
- 现有数据会自动复制到新字段
- 建议执行前先备份
总结
推荐立即执行方案一的修复脚本,这将:
- ✅ 彻底解决车辆ID映射问题
- ✅ 提供多种查询方式
- ✅ 保持系统兼容性
- ✅ 优化查询性能
执行命令:
psql -h localhost -U postgres -d qaup -f sql/fix_vehicle_id_mapping.sql