这是一个“正确”的数据库设计吗?

时间:2012-05-03 08:07:00

标签: sql-server database performance database-design

我正在使用新版本的第三方应用程序。在这个版本中,数据库结构发生了变化,他们说“提高性能”。

旧版本的DB具有如下通用结构:

TABLE ENTITY
(
    ENTITY_ID,
    STANDARD_PROPERTY_1,
    STANDARD_PROPERTY_2,
    STANDARD_PROPERTY_3,
    ...
)

TABLE ENTITY_PROPERTIES
(
    ENTITY_ID,
    PROPERTY_KEY,
    PROPERTY_VALUE
)

所以我们有一个包含基本属性字段的主表和一个用于管理用户添加的自定义属性的单独表。

新版本的数据库有一个这样的结构:

TABLE ENTITY
(
    ENTITY_ID,
    STANDARD_PROPERTY_1,
    STANDARD_PROPERTY_2,
    STANDARD_PROPERTY_3,
    ...
)

TABLE ENTITY_PROPERTIES_n
(
    ENTITY_ID_n,
    CUSTOM_PROPERTY_1,
    CUSTOM_PROPERTY_2,
    CUSTOM_PROPERTY_3,
    ...
)

因此,现在当用户添加自定义属性时,会在当前ENTITY_PROPERTY表中添加一个新列,直到达到最大列数(由应用程序管理),然后创建了一个新表。

所以,我的问题是:这是设计数据库结构的正确方法吗?这是“提高表现”的唯一途径吗?旧的结构需要很多加入或子选择,但这个结构在我看来并不是非常聪明(甚至是正确的)......

5 个答案:

答案 0 :(得分:10)

我之前已经看到了假定的(经常未经证实)加入的“费用” - 它基本上将一个行重的数据表变成一个列重的表。正如你所暗示的那样,当他们用完列时,他们会遇到他们自己的限制。

完全不同意。

就个人而言,我会坚持使用旧结构并重新评估性能问题。这并不是说旧的方式是正确的方式,它只是略微优于我认为的“改进”,并且无需对数据库表和DAL代码进行大规模的重新设计。

这些表格让我觉得很大程度上是静态的... 缓存会在没有破坏数据库的情况下提高性能,而我会先看一下。做一次“昂贵”的抓取并将其粘贴在内存中,然后忘记你的麻烦(请注意,我明白需要管理缓存,但静态数据是最容易管理的一种)。

或者,等待每个数据库遇到最大表数的那一天: - )

其他人建议完全不同的商店。这是一个非常可行的可能性,如果我没有现有的数据库结构,我也会考虑它。也就是说,我认为没有理由为什么这种结构不适合RDBMS。我已经看到它已经在我工作的几乎所有大型应用程序上完成了。有趣的是,它们都沿着类似的路线走下去,所有这些都是“成功”的实施。

答案 1 :(得分:5)

不,不是。它是可怕的。

  

直到达到最大列数(由应用程序处理),   然后创建一个新表。

这句话说明了一切。在任何情况下,应用程序都不应动态创建表。 “旧”方法也不理想,但由于您需要让用户添加自定义属性,因此必须如此。

考虑一下:

  • 您必须将所有值存储在“PROPERTY_VALUE”列中,否则将失去所有类型安全性
  • 根据您的用户,您可以让他们事先更改架构,然后让它们运行某种数据库更新批处理作业,因此至少所有属性都将以正确的数据类型声明。此外,您可能会丢失entity_id / key事物。
  • 看看这个:http://en.wikipedia.org/wiki/Inner-platform_effect。这肯定是它的祸害
  • 也许RDBMS不适合您的应用。考虑使用基于键/值的存储,如MongoDB或其他NoSQL数据库。 (http://nosql-database.org/

答案 2 :(得分:1)


根据我所知的数据库(但我当然不是最有经验的数据库),在您的数据库中执行此操作似乎是一个非常糟糕的主意。如果您已经知道用户可能拥有多少个最大自定义属性,我会说您最好将表格列数设置为该值。

再说一遍,我不是专家,但是在运行中创建新列并不像那样的操作数据库。这会给你带来比任何事情更多的麻烦
如果我是你,我要么修改自定义属性的数量,要么坚持使用旧系统。

答案 3 :(得分:0)

我认为为每个实体创建一个新表来存储属性是一个糟糕的设计,因为你最终可能会使用表来填充数据库。应用第二种方法的唯一方法是,您不会遍历所有不适用于所选实体的冗余行。但是,在原始ENTITY_PROPERTIES表上使用数据库中的索引可以极大地提高性能。

我个人会坚持你的初始设计,应用索引,让数据库引擎确定选择数据的最佳方法,而不是将每个实体属性分成新表。

答案 4 :(得分:0)

没有“正确”的方法来设计数据库 - 除了着名的"normal form"理论之外,我还没有意识到一套普遍认可的标准;由于性能原因,许多数据库设计都忽略了这个标准。

有很多方法可以评估数据库设计 - 性能,可维护性,可懂度等。通常,您必须相互交换这些设计;这就是你的改变似乎正在做的事情 - 交易可维护性和对性能的可懂度。

因此,找出这是否是一个良好的权衡的最好方法是看看性能增益是否已经实现。找到它的最好方法是创建建议的模式,使用代表性数据集加载它,并编写需要在生产中运行的查询。

我猜测,对于像“从STANDARD_PROPERTY_1 ='香蕉'的实体中找到STANDARD_PROPERTY_1这样的查询,新设计的速度会快得多。

我猜测在检索给定实体的所有属性时,它的速度不会明显加快;实际上它可能稍慢,因为新设计需要连接到多个表,而不是单个连接到ENTITY_PROPERTIES。您将返回“稀疏”结果 - 可能并非所有实体都将在所有ENTITY_PROPERTIES_n表的property_n列中包含值。

当新设计可能明显更快时,您需要在自定义属性上使用复合where子句。例如,找到一个实体,其中自定义属性1为true,自定义属性2为香蕉,自定义属性3不在('kylie','pussycat dolls','giraffe')是e`(可能)更快,你可以指定ENTITY_PROPERTIES_n表中的列而不是ENTITY_PROPERTIES表中的行。大概。

至于可维护性 - 哎呀。您的数据库访问代码现在需要更加智能,知道哪个表包含哪个属性,以及有多少列太多。娱乐错误的可能性很高 - 有更多移动部件,我想不出任何明显的单元测试来确保数据库访问逻辑正常工作。

可懂度是另一个问题 - 这个解决方案不在大多数开发人员的工具箱中,它不是行业标准模式。旧的解决方案是众所周知的 - 通常称为“实体 - 属性 - 值”。这成为长期项目中的一个主要问题,您无法保证原始开发团队能够随时待命。