保证空字段是否表明数据库设计不佳?

时间:2014-08-28 23:37:55

标签: database relational-database database-schema

我正在开发一个批处理应用程序,允许用户提交有关特定车辆信息的请求。用户可以使用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"


我认为第一个解决方案更容易查询而不会有任何明显的缺点。应该首选哪种设计?保证空字段真的是糟糕设计的指标吗?

4 个答案:

答案 0 :(得分:2)

您的同事提出的是关于数据库设计的最终反模式。

Google为Bill Karwin的“反模式”一书和“EAV”。

询问你的同事他是如何强制执行“盘子”和“状态”值总是成对出现在他的数据库中。如果他指向应用程序代码,请询问他如何强制执行数据库只能通过他的应用程序更新。

你的解决方案比他好一千倍。仍然“更好”(从涉及避免所有空值的关系纯度的角度来看)是给每种类型的请求自己的表:

VehicleQueriesByVIN

USER_ID(FK)|状态| START_TIME | VIN

VehicleQueriesByPlate

USER_ID(FK)|状态| START_TIME |板|状态

如果要为每个查询保留历史跟踪状态,那么这些东西必须在自己的表中单独列出。

答案 1 :(得分:0)

总之:不。这是一个错位的优化案例。由于存储字符串,他的模式实际上平均会占用更多空间;当然,更复杂的代码和查询会有更糟糕的表现。

答案 2 :(得分:0)

将其视为识别车辆的多种方式。您的车辆有一个或多个身份。当地警察可以使用LPN识别您的车辆,而停车管理局可能使用许可证或主动/被动转发器,此外dmv可能依赖于vrn号码。

如果您真的想构建一种灵活的方式将车辆绑定到多个身份,我会使用身份类型表,这样车辆就可以拥有一个或多个身份。

<强> VehicleIdentity
VehicleIdentity PK
VehicleID FK
IdentityValue
IdentityType(类型)
STATEID?

<强>车辆
VehicelID PK

我通过删除一个我认为没用的表来更新答案:)

答案 3 :(得分:0)

空无一物。它们对单表继承特别有用,如果你的系统需要&#34; Draft&#34;实体。

如果您使用像Postgres这样的质量数据库,则对空值没有存储惩罚。

无论如何,如果问题是&#34;我们需要A或B,A和B非常相似&#34;然后答案几乎总是表继承。如果要快速移动,请使用单表继承。如果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
);