【问题标题】:Database design - adding flags for exceptions/extras数据库设计 - 为异常/额外添加标志
【发布时间】:2014-04-10 21:27:47
【问题描述】:

我正在重新设计一个旧数据库,该数据库一开始很小,现在由于系统更改发生时的多年快速修复而变得非常臃肿和缓慢。 不管这次设计得多么好,当然会有无法预料的变化,所以我正在寻找一些关于如何最好地为这些变化做好准备的一般提示,以及关于我是否走在正确轨道上的一般建议。 我是软件开发/数据库设计领域的新手,所以如果这里有一些明显的问题或者我有点太模糊,请原谅我......我正在尽力:)

具体一点;

将在网站上进行预订。在预订时,可能会添加一些额外/要求,例如预订了一个停车位 - 用户将指出是否需要残疾人空间。 我将创建另一个“DisabledSpacesRequired”表,其中包含一列 - 需要禁用空间的那些的 bookingID。这比在预订表中显示是否需要空间的标志“更好”吗?

同样,预订可能会被取消 - 因此会有一张取消预订的表格。为了稍后搜索,最好简单地在取消的预订表中搜索 bookingID 吗?或者在预订表中有一个标志表明它是否被取消? (无论如何,'CancelledBookings' 表都是必需的,但是否也应该包括一个标志?)

让我想到这些问题的原因是数据库中目前似乎有很多附加组件 - 例如。有一个“订阅者”表,还有一个稍后添加的“订阅者TwitterHandles”表 - 以这种方式分离订阅者类型是一种好习惯吗?或者在现有表中添加标志?

我已经查看了一些类似的问题并经过 Implementing Review flags in Databases; best practices 我认为最好将变量分开,为将来可能发生的变化做准备。 (例如,我们可能想要添加一些与所需的残疾人停车位相关的信息。)

希望我很清楚 - 非常感谢任何建议。

【问题讨论】:

    标签: sql database schema


    【解决方案1】:

    关于数据库中的标志有很多意见。所以常见的答案是“嗯,这取决于你希望你的 RBDMS 做什么”。

    我每天使用的学生信息系统在基本学生表中有一个状态标志。合法值是 A - 活跃、I - 不活跃、P - 预注册和 G - 毕业。没有验证表或查找表。它在应用程序中是硬编码的。虽然相对而言这是一个问题,但该应用程序运行良好。一个学生总是只有一个身份,并且没有任何情况不在现有的身份列表中。您可以添加一个regtb_status 查找表并向学生注册表添加一个外键约束,但这并没有给这个应用程序添加太多内容。

    对于您的预订示例,我将在预订表本身中有一个当前状态字段。我更喜欢使用字符字段,这样我就可以支持我知道我可能需要的状态:A - 活动,C - 客户取消,I - 无效,D - 员工删除等。您甚至可以允许客户可以访问验证表,以便他们可以根据需要创建自定义状态。这取决于您设想的工作流程和您的客户想要的。

    在同一系统的其他地方,有很多状态标志字段是硬编码的CHAR(1) 字段,它们是 Y - Yes 和 N - No。您可能应该为这些标志使用 RDBMS 的布尔类型,但除非您'正在谈论荒谬的记录数量或需要担心国际化,这不会成为问题。这些类型的表通常也用作连接表。例如,将学生与联系人相关联的表格包括联系人是否与学生同住、联系人类型(监护人、紧急联系人)、联系人与学生的关系(母亲、父亲、阿姨等)的状态标志.),该联系人是否应该可以访问家长网站中的学生,联系人的优先顺序,家长是否应该在邮件中收到成绩单等。这个特定的表格有点麻烦,因为有此表中有十几个标志字段,但多个标志选项关系类型可以在应用程序的验证/查找表中完全配置,并且列名至少部分是自记录的。从撰写报告的角度来看,这是非常宝贵的。

    我们有一些字段存储在用户定义的表中,它们实际上将所有内容存储在数据库中的 EAV 表中。这些会导致问题,因为通常情况下,特定的 EAV 记录在学校明确设置之前并不存在。应用程序的行为就像 null = No,但它会使编写报告甚至在应用程序中搜索变得困难。你不能寻找field = 'N'。你必须寻找field = 'N' OR field IS NULL。在应用程序的搜索系统中,您必须指定field <> 'Y',因为它在所有情况下都不能很好地处理空值。对于无法围绕三个有价值的逻辑进行思考的用户来说,这非常令人困惑。这对于 DBA 来说也是相当烦人的,因为查看数据的最佳方式,即视图,不容易更新。

    根据我的经验,位掩码几乎总是不正确。查询它们非常麻烦且成本高昂,不能自我记录,而且通常会带来巨大的痛苦。我宁愿每天看到一系列BIT/BOOLEANCHAR 字段,也不愿看到位掩码。如果它在一个字段中有多个属性,那将是一个巨大的问题。

    对于您的 SubscribersTwitterHandles 问题,我想我有点困惑。他们为什么不直接在现有表中添加一列?是一对多的关系,还是有多个 Twitter 句柄字段?要么你的客户没有给你他们的句柄——在这种情况下,它明确地是''——或者是他们给你的句柄。

    我想从设计的角度来看我真正的问题:我们是在创建 flags 还是 tags?在我看来,标志是与数据库中现有实体具有一对一关系的东西。该实体可能是两个实体之间的连接点,也可能位于实体本身上,但它始终具有非空值。

    另一方面,标签是任意的,可能是多对一或多对多,并且在大多数情况下完全由客户定义为对记录进行分组的临时手段。

    【讨论】:

    • 哇,非常感谢您提供的所有见解!了解一些工作示例非常有帮助——“规则”如何因使用而异。我在这里谈论的是标志的最佳实践 - 具有一对一的关系。我需要坐下来找出最适合这个数据库的方法!目前的主要问题是搜索缓慢,所以这是我需要关注的。再次感谢:)
    【解决方案2】:

    我试图从数据库设计的角度分享我的观点,

    • 请尝试考虑您的实体及其属性。在关系数据库设计中,属性映射到列,实体映射到表。
    • 如果您同意如果新添加的主题可以是实体本身,那么最好为它创建一个新表并与其他表建立关系,您可以使用外键关系,也可以是另一个表来保持关系。
    • 如果您认为它只能是现有实体的另一个属性,那么最好在该表中添加一列。

    这些是非常基本的数据库设计技术,但人们有时也会进行权衡,而不是为了更容易编码/查询。但我认为这可能是另一回事。

    【讨论】:

      【解决方案3】:

      这取决于:)

      您必须了解如何使用数据。如果您有数万亿个表作为标志,您的查询将包含大量连接来检索所有信息。

      如果您不想在这些列中进行搜索,那么它可以是一个标志列(或一个单独的表,用于包含多列的所有标志)。您可以在某些 RDBMS 中存储多个标志(例如 MySQL 的 'enum' 和 'set' 类型)。您还可以将标志存储在位掩码(整数)中。

      如果您想搜索这些标志(并且该标志是主要过滤器),单独的表格可能会有所帮助。只需加入这些表就可以了,但是使用多个搜索条件将很难实现。 (想象一下,当您要搜索请求停车场标志或禁用槽的所有记录时)

      您还可以将它们存储在键值“对”(bookingId、flagType)中,这在需要设置自定义标志时很有用。

      再一次:了解您的数据并了解您的 RDBMS 是如何工作的。您必须考虑要优化存储空间或其他资源(cpu 使用率、内存、磁盘 IO 等)。总会有好处和坏处。当您无法确定哪种实现最好时,请设置一些测试用例并衡量最重要的指标以获取更多信息。

      编辑:我认为,在您的具体情况下,这些标志不会充当过滤器,因此您可以将它们存储在一列中(每个单独一个或分组为位掩码)。

      【讨论】:

      • 感谢 Pred 的建议。不会有大量用于标志的表 - 所以我最多想象一个查询中需要 2 或 3 个连接。将对这些数据进行大量搜索,并且通常根据标志进行,所以我认为单独的表可能会更好;通常不会有多个搜索条件。
      猜你喜欢
      • 2014-01-19
      • 1970-01-01
      • 2011-06-08
      • 2021-08-19
      • 1970-01-01
      • 2016-05-24
      • 2012-07-29
      • 2022-11-27
      • 2010-09-08
      相关资源
      最近更新 更多