2014-08-28 64 views
1

我正在開發一個批處理應用程序,允許用戶提交有關特定車輛信息的請求。用戶可以使用VIN或牌照/州組合提交請求。我提出如下表結構:確保空字段表示數據庫設計不佳?


VehiclesToBeProcessed

vehicle_id(fk)|user_id(fk)|status|start_time

車輛

vehicle_id|VIN|plate|state


我的同事認爲,這是設計不良,因爲每一個紀錄 車輛將具有空的VIN字段,或者空板和狀態字段。相反,他們提出以下建議:
VehiclesToBeProcessed

vehicle_id(fk)|user_id(fk)|status|start_time

車輛

vehicle_id(pk)|field|value

其中車輛條目要麼由一排的VIN :

1|"vin"|"123

或兩行的板/狀態:

2|"plate"|"abc 123" 2|"state"|"NY"


我認爲第一解決方案將是更容易查詢,而無需任何顯著缺點。哪個設計應該是首選?保證空字段真的是糟糕的設計指標嗎?

+0

我不知道它應該如何處理板/狀態的兩行。如果'vehicle_id(pk)'是一個主鍵,那麼你不能有2行具有相同的vehicle_id。 此外,據我所知,每輛車必須有VIN(可能未知),但不是板。此外,板塊數量隨時間變化(可能會改變)。 – a1ex07 2014-08-29 00:04:35

回答

1

提出你的同事約在數據庫設計的最終反模式的答案更新。

Google針對Bill Karwin的「反模式」書和「EAV」。

詢問你的同事他是如何強制執行的,「板塊」和「狀態」值總是在其數據庫中成對出現。如果他指出應用程序代碼,請問他如何強制執行該數據庫只會通過他的應用程序更新。

你的解決方案比他的好一千倍。仍然「更好」(從它涉及避免所有空值關係純度的角度來看)是給每個類型的請求它自己的表:

VehicleQueriesByVIN

USER_ID(FK)|狀態| START_TIME | VIN

VehicleQueriesByPlate

USER_ID(FK)|狀態| START_TIME |板|狀態

如果歷史軌跡是隨着時間的推移將保持狀態的每個查詢,這些東西在自己的表中被挑選出來。

0

一句話:沒有。這是錯位優化的一個例子。由於存儲字符串,他的模式實際上將平均佔用更多的空間;當然,更復雜的代碼和查詢的性能會更差。它

0

想象的那樣多種方式來識別車輛。你的車輛有一個或多個身份。當地警方可能會使用LPN識別您的車輛,而停車管理當局可能使用許可徽章或主動/被動應答器,此外,dmv可能依靠vrn號碼。

如果你真的想建立一個車輛多重身份,我會用一個標識類型表綁定一個靈活的方式,使車輛能夠具有一個或多個身份。

VehicleIdentity
VehicleIdentity PK
VehicleID FK
IdentityValue
IdentityType(類型)
STATEID ??

車輛
VehicelID PK

我通過刪除一個表,我看就沒有用:)

0

空值很好。它們對於單表繼承非常有用,並且您的系統需要「草稿」實體。

如果您使用像Postgres這樣的質量數據庫,則不存在空值的存儲處罰。不管怎樣,如果問題是「我們需要A或B,而A和B非常相似」,那麼答案几乎總是表繼承。如果你想快速移動然後使用單表繼承。如果NULL讓你難過,那麼使用Class Table Inheritance。

--STI: 
create table vehicle_identifiers (
    id int primary key, 
    type text not null check (type in ('VIN', 'STATE_N_PLATE')) 
    vin null, 
    state char(2) null, 
    plate text null, 

    check ((type='VIN' and vin is not null) or (type='STATE_N_PLATE' and state is not null and plate is not null)) 
); 

--CTI: 
create table vehicle_identifiers (
    id int primary key 
); 

create table vehicle_identifiers_vin (
    id int primary key references vehicle_identifiers(id), 
    vin text not null 
); 

create table vehicle_identifiers_state_n_plate (
    id int primary key references vehicle_identifiers(id), 
    state text not null, 
    plate text not null 
);