当前位置: 首页 > 面试题库 >

如何设计数据库架构以支持类别标记?

贾烨
2023-03-14
问题内容

我正在尝试像“数据库设计标签”之类的东西,除了我的每个标签都分为几类。

例如,假设我有一个有关车辆的数据库。假设我们实际上对车辆不是很了解,因此我们无法指定所有车辆将具有的列。因此,我们将用信息“标记”车辆。

1. manufacture: Mercedes
   model: SLK32 AMG
   convertible: hardtop

2. manufacture: Ford
   model: GT90
   production phase: prototype

3. manufacture: Mazda
   model: MX-5
   convertible: softtop

现在,您可以看到所有汽车都标有其制造商和型号,但其他类别并不完全匹配。请注意,汽车只能具有每个类别中的一个。IE。一辆汽车只能有一个制造商。

我想设计一个数据库来支持对所有梅赛德斯的搜索,或者能够列出所有制造商。

我当前的设计是这样的:

vehicles
  int vid
  String vin

vehicleTags
  int vid
  int tid

tags
  int tid
  String tag
  int cid

categories
  int cid
  String category

我拥有正确的主键和外键,但我无法处理每辆车只能由一个制造商处理的情况。还是可以吗?

我可以在vehicleTags的复合主键中添加外键约束吗?IE。我是否可以添加一个约束,使得仅当VehicleTags中没有一行时才可以将复合主键(vid,tid)添加到vehicleTags中,从而对于同一个vid,with中已经没有tid了。相同的CID?

我的猜测不是。我认为解决此问题的方法是将一个cid列添加到vehicleTags,并制作新的复合主键(vid,cid)。它看起来像:

vehicleTags
  int vid
  int cid
  int tid

这样可以防止汽车拥有两个制造商,但现在我重复了cid中tid的信息。

我的架构应该是什么?

Tom在我之前的问题“您如何进行多对多表外部联接”时在数据库html" target="_blank">模式中注意到了此问题?

编辑
我知道在示例中制造应该确实是车辆表中的一列,但是让我们说您不能这样做。这个例子只是一个例子。


问题答案:

这是Entity-Attribute-Value设计的又一个变体。

更加易于识别的EAV表如下所示:

CREATE TABLE vehicleEAV (
  vid        INTEGER,
  attr_name  VARCHAR(20),
  attr_value VARCHAR(100),
  PRIMARY KEY (vid, attr_name),
  FOREIGN KEY (vid) REFERENCES vehicles (vid)
);

有些人强迫attr_name引用预定义属性名称的查找表,以限制混乱。

您要做的只是将一个EAV表分布在三个表上,而没有改善元数据的顺序:

CREATE TABLE vehicleTag (
  vid         INTEGER,
  cid         INTEGER,
  tid         INTEGER,
  PRIMARY KEY (vid, cid),
  FOREIGN KEY (vid) REFERENCES vehicles(vid),
  FOREIGN KEY (cid) REFERENCES categories(cid),
  FOREIGN KEY (tid) REFERENCES tags(tid)
);

CREATE TABLE categories (
  cid        INTEGER PRIMARY KEY,
  category   VARCHAR(20) -- "attr_name"
);

CREATE TABLE tags (
  tid        INTEGER PRIMARY KEY,
  tag        VARCHAR(100) -- "attr_value"
);

如果要使用EAV设计,则只需要vehicleTagscategories表。

CREATE TABLE vehicleTag (
  vid         INTEGER,
  cid         INTEGER,     -- reference to "attr_name" lookup table
  tag         VARCHAR(100, -- "attr_value"
  PRIMARY KEY (vid, cid),
  FOREIGN KEY (vid) REFERENCES vehicles(vid),
  FOREIGN KEY (cid) REFERENCES categories(cid)
);

但是请记住,您正在 将数据与元数据混合在一起 。您将无法将某些约束应用于数据模型。

  • 如何使其中一个类别成为强制性类别(常规列使用NOT NULL约束)?
  • 如何使用SQL数据类型来验证某些标记值?不能,因为您为每个标记值使用了一个长字符串。该字符串是否足够长,可以容纳将来需要的每个标签?你不知道
  • 您如何将某些标签限制为一组允许的值(常规表使用外键查找表)?这是您的“软顶”与“软顶”示例。但是您不能对tag列进行约束,因为该约束将应用于其他类别的所有其他标签值。您还可以有效地将引擎大小和油漆颜色限制为“软顶部”。

SQL数据库不适用于此模型。正确的做法非常困难,查询变得非常复杂。如果您确实继续使用SQL,则最好按常规对表建模,每个属性只有一列。如果需要“子类型”,则为每个子类型定义一个从属表(Class-
Table
Inheritance

),否则使用Single-
Table
Inheritance。如果每个实体的属性都有无限的变化,请使用Serialized
LOB。

针对此类流动的非关系数据模型而设计的另一项技术是语义数据库,该数据库将数据存储在RDF中并通过SPARQL查询。一种免费的解决方案是RDF4J(以前称为Sesame)。



 类似资料:
  • 主要内容:一、用一个创业公司的发展作为背景引入,二、多台服务器分库支撑高并发读写,三、大量分表来保证海量数据下的查询性能,四、读写分离来支撑按需扩容以及性能提升,五、高并发下的数据库架构设计总结这篇文章,我们来聊一下对于一个支撑日活百万用户的高并系统,他的数据库架构应该如何设计? 看到这个题目,很多人第一反应就是: 分库分表啊! 但是实际上,数据库层面的分库分表到底是用来干什么的,他的不同的作用如何应对不同的场景,我觉得很多同学可能都没搞清楚。 一、用一个创业公司的发展作为背景引入 假如我们现在

  • 主要内容:一般业务系统运行流程图,一台 4 核 8G 的机器能扛多少并发量呢?,高并发来袭时数据库会先被打死吗?,8 核 16G 的数据库每秒大概可以抗多少并发压力?,数据库架构可以从哪些方面优化?,总结今天给大家分享一个知识点,是关于 MySQL 数据库架构演进的,因为很多兄弟天天基于 MySQL 做系统开发,但是写的系统都是那种低并发压力、小数据量的,所以哪怕上线了也就是这么正常跑着而已。 但是你知道你连接的这个 MySQL 数据库他到底能抗多大并发压力吗?如果 MySQL 数据库扛不住压力

  • 我想用com。Android支持:设计:22.2.0在我的Android Studio(1.3)项目中,但当我添加'com'时。Android支持:设计:22.2.0'到依赖{}我有103个错误,我无法摆脱这个错误。 如果我尝试使用新版本的appcompat,也会发生同样的情况。现在我有了“com”。Android支持:appcompat-v7:19。“以我的身材。格雷德尔。 有人知道吗? 我的错

  • 1、数据库设计最起码要占用这个项目开发的40%以上的时间 2、数据库设计不仅仅停留在页面demo的表面 页面内容所需字段,在数据库设计中只是一部分,还有系统运转、模块交互、中转数据、表之间的联系等等所需要的字段,因此数据库设计绝对不是简单的基本数据存储,还有逻辑数据存储。 3、数据库设计完成后,项目80%的设计开发都要存在你的脑海中 每个字段的设计都要有他存在的意义,要清楚的知道程序中如何去运用这

  • CodeIgniter 的目标是在最小化,最轻量级的开发包中得到最大的执行效率、功能和灵活性。 为了达到这个目标,我们在开发过程的每一步都致力于基准测试、重构和简化工作, 拒绝加入任何对实现目标没有帮助的东西。 从技术和架构角度看,CodeIgniter 按照下列目标创建: 动态实例化。 在 CodeIgniter 中,组件的导入和函数的执行都是在被请求的时候 才执行,而不是全局的。除核心资源外,

  • 问题内容: 设想 我正在建立一个包含一系列不同表的数据库。这些由COMMENTS表,BLOGS表和ARTICLES表组成。我希望能够向每个表中添加新项目,并使用0到5个标签对其进行标记,以帮助用户更轻松地搜索相关的特定信息。 有关建筑的初步想法 我最初的想法是拥有一个集中的TAGS表。该表将使用TagID字段和TagName字段列出所有可用标签。由于每个项目可以有很多标签,并且每个标签可以有很多项