我试图权衡一个简单的数据库结构的相对优缺点,例如:
1。的
CREATE TABLE x (
my_id INT PRIMARY KEY,
...,
text_attribute_blah TEXT,
text_attribute_blah_blah TEXT
);
VS
2。的
CREATE TABLE x (
my_id INT PRIMARY KEY,
...
)
CREATE TABLE attributes (
my_id INT, /* foreign key to x.my_id */
text_attribute_type INT,
text_attribute TEXT
)
其中attribute_type可能是blah或blah_blah。
选项1提供简单性 - 表更易于读/写;选项2提供了灵活性(如果我们想要添加另一个属性,例如blah_blah_blah,我们不需要进行架构更改,因此代码更改可能更少。)
这个难题有正确/错误的答案吗?其中一种选择是否比其他选择更好?你能指点我进一步阅读可能有助于确定前进的方向吗?
答案 0 :(得分:10)
我几乎总是选择#1 - 我更喜欢在我的表中将属性作为列 - 使查询,性能索引以及一般处理更容易和更透明。
#2选项称为EAV - 实体属性值 - 它有一些主要缺点 - 见
答案 1 :(得分:3)
有趣的是,您没有提及性能或数据完整性。对于它的价值,模型#1是考虑这些因素的最佳方法。
就数据模型而言,灵活性被高估了。大多数表结构在开发开始时都是众所周知的,并且在数据库的整个生命周期内保持稳定。如果你有一个模型真正流畅且不可知的应用程序,那么你可能根本就不应该使用RDBMS。选择其中一个NoSQL产品。
这是对#1的另一次投票。
答案 2 :(得分:3)
每个解决方案都有问题需要解决。如果您事先知道所需的列,那么#1将是一个很好的方法。但是,在某些情况下,列不是预先知道的。例如,用户添加到功能的自定义字段。
话虽如此,EAV有很多问题。如果使用得当,IMO很有用。
答案 3 :(得分:2)
选项1几乎每次都有。选项2效率很低。当你必须以更高效的方式做某事时,轻松查询也很笨拙。话虽如此,我已经看到许多产品为用户定义的属性执行此操作。使用选项2技术的系统示例包括Agresso和Kalido.
如果您正在进行定制应用程序,那么添加属性的最佳方法就是在需要时扩展数据库架构。由于更改将伴随对代码的修改,因此可以作为发布过程的一部分来完成。
如果您正在打算打算让客户自行配置的打包应用程序,那么您可以采取三种方法。
EAV结构与选项2类似。这是灵活的,但查询效率低,特别是当查询复杂多个连接时。
在表格上创建一组“用户”字段(User1,User2等)。这会将您限制为有限数量,但这可能非常大(如果您愿意,可以使用User01-User99)。但是,查询是最有效和最简单的。另一个问题是这些字段有些不透明。您必须能够访问配置信息才能了解“User3”的含义。它也牺牲了一些类型的安全性。但是,总的来说,您的用户字段机制将拥有一些自己的元数据和某种类型的通用框架,因此可以通过此方式提供某些类型的安全性。
这看起来最多不优雅,但在大多数情况下是最好的方法,因为它具有最佳性能和最简单的查询。这是迄今为止最简单的方案。
XML。这是无限灵活的,但是围绕数据库的大多数工具在使用XML方面做得很差。它还将XML存储在主表的单独分配单元中,因此可能会导致查询性能出现严重问题。基于XML的策略是以应用程序为中心的,其代价是数据的其他消费者。
根据我的经验,在数据库的XML字段中存储大量数据将大大提高应用程序的TCO。在大多数情况下,不建议用户数据字段。
答案 4 :(得分:1)
@marc_s 我不相信人们可以“几乎总是”在上述选项中做出任何选择。有一种情况可以支持这两种解决方案。
选项#1 当实体X被很好地定义时也可以这样做,即你确切地知道你需要捕获什么来定义X.在这种情况下,X的单个记录几乎捕获了X的一个实例代表的所有内容。
选项#2 当这样的实体X不能被完全定义时,即你不知道需要什么样的属性来“完全”定义它。
例如以“你应该避免的五个简单的数据库设计错误”一文中提到的员工记录为例[链接由@marc_s提供]。是!!!您将很想获得选项1,但如果您考虑在大型组织中工作的员工的情况,一旦单独记录员工信息 - 其定义和内容都是高度动态的,并且需要选项#1和选项#2的组合。
答案 5 :(得分:1)
@marc_s
虽然我提到了员工记录的例子,但我确信这不是很有说服力。
以下是金融领域的示例。
如果要捕获交易的所有属性,则取决于其工具类型。捕获大多数外汇,货币市场甚至债券工具都非常容易,因为它们非常有条理。 但随着我们转向衍生产品,它变得非常麻烦。它们在性质上非常奇特,并且在结构方面不断变化(因此其意义等)。要捕获这种动态变化的信息,我们应该选择EAV。当然,在做出这个选择时,应该意识到它会在你的评论中带来许多负面因素。
我不能谈论其他领域,但我相信你会发现许多业务领域的IT系统都面临这种情况,因此对EAV策略有很好的理解 - 反对它的彻底拒绝 - 将是一个好的想法。
Shrini
答案 6 :(得分:0)
如前所述,这取决于您的要求。只有在需要时才应选择#2,例如,在程序工作流程中添加新类型的属性。通过在表中添加新列来执行此操作肯定比在查询中添加一个额外的表和一个额外的连接更糟糕。