【问题标题】:Advice for Denormalization非规范化建议
【发布时间】:2013-02-05 22:40:49
【问题描述】:

我有一个学区数据库(其中约 15,000 个,并且还在不断增加)以及每个学区的员工可获得的退休计划/福利。数据已经很好地标准化了:

  • 地区记录与 0 或 n 个退休计划选项相关联(其中 n
  • 地区记录与 0 或 n 个福利相关联(其中 n 与 1 个连接表中的 40 更接近)
  • 一个地区还与其他一些关联数量很少的事物相关联。

现在客户想要报告。他们希望以一种非常动态的方式进行报告(想想一个 iTunes 智能播放列表,其中可以为任何地区、计划或福利的任何财产添加/删除规则)。我需要允许他们查询某个地区的任何财产、退休计划或福利并返回所有内容

为了使事情简单(目前)并避免重复数据,我设置了几个视图(嘘,我知道)只允许我以任何 1 个区记录有效的方式访问数据与all_retirement_plans 视图的一对一关系和与all_benefits_plans 视图的一对一记录。这为我提供了一组干净的连接,从而产生了一个统一的结果集,但显然有它自己的一组问题,我将尽快解决这些问题......

也就是说,随着更多数据的添加,它会变得荒谬

我正在寻找一些关于非规范化的建议。我考虑过一个报表,它可以完成视图的功能,但可以被索引。我还考虑过将整套地区数据转储到 MongoDB(或类似的)。我确信还有其他选择,但我会玩试错游戏,所以我希望这里的人能以一种让我保持在合理解决方案的范围内的方式向我提供建议。

最重要的是,我需要能够存储大约 15,000 条(并且还在增长的)地区记录以及大量额外的元数据,然后以非常精细的级别报告这些数据。除了我自己的想法之外,有人有任何想法或建议吗?我正在努力提前解决我知道即将发生的问题。

【问题讨论】:

  • “我已经设置了几个视图(嘘,我知道)...” 视图是 SQL 数据库管理系统的基本功能。当您必须同时使用 viewsshhh 时,您应该考虑切换到不同的 dbms。
  • 我有点傻,但事实是,视图可能不是满足这种特殊需求的正确平台。考虑到数据的大小(特别是非规范化后的列数),视图的速度与我预期的一样慢。我不知道有什么方法可以优化它们,但我很想弄错。
  • 获得更好性能的一种方法是切换到具有更好查询优化器的 dbms。
  • 那么这些all_retirement_plansall_benefits_plans 视图是否使用GROUP_CONCAT 来聚合和连接所有不同的字符串?
  • @ruakh - 如果我理解你的问题,不。没有进行字符串连接。我面前没有确切的数字,但每个地区可能有 0 个或更多约 30 种不同的福利,并且福利记录有一些属性。 all_benefits_pans 视图包含一个地区记录,其中包含每个福利的每个属性。它最多可添加约 100 列。

标签: mysql optimization nosql denormalization


【解决方案1】:

我希望这会有所帮助,因为我最近在将数据从关系数据迁移到面向文档(非规范化)方面做了很多工作。

将数据移动到 Mongo 的一些选项:

  1. 您可以轻松地将数据从 MySQL 写入 Mongo 并保留您的关系表。无需转换,只需直接移动数据即可。 Mongo 具有可以输出到新集合的 map/reduce。虽然很慢。 =( 如果你直接移动一个视图,Mongo 有一个聚合框架,对于生成新文档非常强大。

  2. 理想情况下,您应该在 MySQL 中编写“文档”,然后将它们移过来。我使用 MySQL 的经验是使文档非常扁平。您可以通过 group_concat 发挥创意来添加结构。你基本上 group_concat 一些数据和手动 JSON 字符串在一起。 (丑陋,但有效)

  3. Mongo 在处理文档方面非常出色。真的,真的很棒。如果您想处理非规范化数据,我强烈推荐它。

  4. 这可能有点矫枉过正,但我​​们使用 Mule ESB 将数据从 MySQL 移动到 Mongo。您可以在那里进行更复杂/棘手的转换,但有一个学习曲线。

  5. 在 SQL Server 中,您可以将查询输出为 XML。如果您可以在 MySQL 中找到一个库来执行此操作,那么从 XML 到 JSON 的跳转很容易。我们已经能够在 SQL Server 中运行超过 10 万条记录的查询并非常快速地输出 XML。

如果您想了解任何要点的更多详细信息,请告诉我。 =)

【讨论】:

  • 谢谢,瑞恩。我首先想确定,如果我迁移到 Mongo,我仍然可以执行非常精细的查询。 MongoDB“文档”将代表一个地区(包括其所有退休计划/福利数据),因此我可以将这些作为嵌套组件包含在内,也可以将其全部展平,如您所提到的。听起来平面更快?我得看看group_concat
  • Flat 更容易从 MySQL 迁移到 Mongo。 Mongo 有非常丰富的查询语言。语法可能需要一些时间来适应,但你肯定可以完成很多。 group_concat 可以创建数组或子文档。
  • 终于看了group_concat。这不完全是我所拥有的。我没有连接字段值,而是拼合记录。如果一个地区可能有 3 个可能的福利记录(每个都有一个 ID 和一个提供者),我将这些福利记录中的每一个平展到视图中,以便一个地区现在有 1 个福利记录,其中包含前缀以区分的字段。例如,accident_insurance_idaccident_insurance_providerdental_iddental_provider 等。现在我的districts 表与此视图是一对一的关系。
  • 我想,我最初的想法是将district 扁平化,以便地区文档在 MongoDB“文档”中包含所有退休和福利计划信息。每个地区的文件都非常大(大约 150 处左右),其中有 15-20K 并且还在增长。就性能而言,该猜测中有任何危险信号吗?
  • 是的,Mongo 和文档/文档大小需要注意一些事项。 Mongo 的文档限制为 16MB。你不能越过它。 Mongo 也有一个微妙的假设,即您的文档不会增长太多。如果它变得太大,Mongo 必须将其移出当前内存位置并找到一个新位置。这可能会导致 RAM 碎片化并使事情变慢。如果您的某些数据经常更改,我可能会建议使用参考链接到它,而不是将其嵌入到主文档中。
猜你喜欢
  • 2018-03-12
  • 2011-06-22
  • 1970-01-01
  • 2012-01-28
  • 2013-08-21
  • 2016-05-13
  • 2018-06-06
  • 2016-05-27
  • 2021-06-13
相关资源
最近更新 更多