QDAirPortBackend0122/doc/work/车辆ID映射解决方案_20250115.md
2026-01-22 13:19:47 +08:00

5.8 KiB
Raw Blame History

车辆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';

执行步骤

立即执行(推荐)

  1. 备份数据(重要)

    pg_dump -h localhost -U postgres -d qaup > backup_before_fix_$(date +%Y%m%d_%H%M%S).sql
    
  2. 执行修复脚本

    psql -h localhost -U postgres -d qaup -f sql/fix_vehicle_id_mapping.sql
    
  3. 验证结果

    -- 检查新字段
    \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
    }
}

使用建议

开发中的最佳实践

  1. 统一使用车牌号作为业务标识符

    -- 推荐:使用车牌号查询
    SELECT * FROM vehicle_info_with_location WHERE vehicle_plate = '京A12345';
    
  2. 数据插入时同时设置两个字段

    INSERT INTO vehicle_locations (vehicle_id, license_plate, sys_vehicle_id, ...)
    VALUES ('京A12345', '京A12345', 1001, ...);
    
  3. 定期执行数据同步

    -- 如果有新的车辆信息录入,执行同步
    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