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