【问题标题】:Database denormalization opportunity数据库非规范化机会
【发布时间】:2010-09-17 20:38:50
【问题描述】:

我正在寻找一种策略,以阻止重复出现分支表的问题。例如,作为一个虚构的用例,假设我有一个包含用户名、登录名、密码和其他元数据的用户表。在这个特定的场景中,假设用户被限制为每个特定的 IP 子集登录。因此,我们有一个 1:M 的关系。每次出现诸如以下的用例时,您的正常工作流程包括拥有一个“用户”表和一个诸如“user_ips”之类的表,在这种情况下,您将拥有诸如 pk(ip_id)、fk( user_id) 和 user_ips 端的 IP。

对于类似的情况,你们通常会按照上面的方式扇出吗?这里有机会有效地去规范化吗?也许以某种 CSV 分隔的方式将 IP 存储在 BLOB 列中?你们今天正在部署哪些策略?

【问题讨论】:

    标签: mysql database database-design denormalization normalizing


    【解决方案1】:

    一种选择是将您的 IP 地址存储为 xml 字符串。我认为这比逗号分隔的列表更好,并且允许您在需要时灵活地将其他元素添加到字符串中(想到端口)而无需更改数据库。

    虽然,我认为在大多数情况下标准化的时尚更好。

    【讨论】:

    • 好主意 - 您甚至可以将其存储为 JSON 并减少存储空间需求。
    • 哦,请不要。我们正在经历将数据从 XML 字符串中拉回到列中的过程。假设有一天您需要选择具有给定属性的所有用户。玩得开心!在许多用户之间更新相同的值也是如此——您必须重建每个 XML 块。
    • @Just Some Guy - 哎呀,没想到是这样的!
    【解决方案2】:

    我怀疑,当潜在相关项目的数量很大时,任何规范化解决方案都会在正确索引的情况下执行非规范化解决方案。我的策略是规范化数据库,然后提供视图或基于表的函数,利用索引连接来使成本可以承受。我会让性能要求决定向非规范化形式的转变。

    请记住这一点。如果您需要对部分信息实施基于角色的安全访问,则基于表的安全性比基于列的安全性更容易实施,尤其是在数据库或数据层级别。

    【讨论】:

      【解决方案3】:

      我强烈建议反对在一个字段中放置多个 IP 地址。没关系 3NF 这打破了 1NF。

      Tvanfsson 是正确的,如果您为 FKEY 编制索引,您将获得相当可观的性能,除非“users_ips”表中有数百万条记录。

      更好的是,通过保持这些表的规范化,您实际上可以在将来报告这些信息,以便当用户对为什么他们无法从某些 LAN 登录感到困惑时,编写应用程序(或 SQL)来进行故障排除并且用户 IP 查找会很多更容易。

      【讨论】:

        【解决方案4】:

        与任何非规范化问题一样,您需要考虑与之相关的成本。特别是,如果您在主表中列出 IP 地址,您将如何回答“哪些用户可以与 IP 地址 w.x.y.z 关联?”这个问题。使用完全规范化的形式,这很容易并且与“哪些 IP 地址可以与用户 pqr 相关联?”对称。对于非规范化形式,问题的答案非常不同。此外,在非规范化版本中,确保应用正确的完整性规则通常要困难得多。

        【讨论】:

          【解决方案5】:

          机会去规范化?我认为您可能误解了传统智慧 - 非规范化是一种 优化 技术。不是你出去寻找的东西。

          【讨论】:

          • 我完全同意。想象一下创建一个更新查询来删除一个 IP。或者找出哪些用户使用相同的 IP。我已经开始头疼了。
          • +1 - 显然需要至少几年的查询优化经验才能被允许使用“非规范化”这个词。用剪刀跑步。
          【解决方案6】:

          您可能需要考虑一个用户属性表和属性类型表,您可以在其中定义用户可以拥有的属性类型。每个新的用例都将成为一个属性类型,数据将简单地添加到用户属性表中。

          使用您的 IP 地址示例,您将拥有 IP 属性类型并将相应的 IP 存储在用户属性表中。这使您可以灵活地添加其他类型,例如 MAC 地址,并且不需要您创建新表来支持新的数据类型。对于每个新用例,您无需添加任何数据。

          不利的一面是,鉴于此属性结构,您的查询会稍微复杂一些。

          【讨论】:

            【解决方案7】:

            恕我直言,这完全是关于成本/收益分析。一切都取决于您使用的平台的要求(包括可能的要求)和功能。

            例如,如果您有“显示系统中记录的所有唯一 IP 地址”之类的要求,那么您最好现在“分支”并创建一个单独的表来存储 IP 地址。或者,如果您需要对 IP 地址进行某些限制(例如“给定用户的所有 IP 地址必须是唯一的),那么您可能会从单独的表和对其应用适当的限制中受益匪浅。(请注意,您甚至可以同时满足这两个要求如果您使用了非规范化设计和适当的与 XML 相关的机制;但是,针对这些要求的基于 RelDB 的解决方案似乎在实施和维护方面要便宜得多。)

            显然,这些并不是要求规范化解决方案的唯一示例。

            同时,我认为“显示用户的所有 IP 地址”或“显示与给定 IP 地址关联的所有用户”之类的要求可能不足以证明标准化解决方案的合理性。

            您可以尝试进行更深入的分析(寻找第一类需求),或者仅仅依靠您对项目上下文(当前和未来)的理解以及您的“直觉”。

            在这种特殊情况下,我自己的“胆量”是第一种类型的要求(支持规范化的要求)极有可能,所以从一开始就使用规范化的解决方案会更好。但是,您已经说过这个用例是虚构的,因此在您的实际情况下,结论可能完全相反。

            永远不要说“从不”:3NF 并不总是最好的答案。

            【讨论】:

            • 你说的很对,3NF 并不总是答案。 BCNF 更强大,有时除了破产并使用 PJNF 之外别无他法。
            • 而且,更重要的是,当您处于 BCNF 时,通常您也处于 5NF 或 PJNF。
            猜你喜欢
            • 1970-01-01
            • 2013-01-18
            • 2016-07-23
            • 2016-11-18
            • 2018-02-07
            • 2012-11-18
            • 2011-11-12
            • 2011-09-24
            • 2017-01-14
            相关资源
            最近更新 更多