针对多对多关系的高效持久性策略

时间:2014-04-07 01:19:22

标签: database data-structures set

TL; DR:我应该使用SQL JOIN表还是Redis集来存储大量的多对多关系

我有内存中的对象图结构,其中我有一个“多对多”索引,表示为有序集之间的双向映射:

group_by_user |  user_by_group
--------------+---------------
louis: [1,2]  |   1: [louis]
john: [2,3]   |   2: [john, louis]
              |   3: [john]

我需要能够执行的基本操作是对各个集合进行原子“插入”和“删除”操作。我还需要能够进行有效的密钥查找(例如,查找用户所属的所有组,或查找作为一个组成员的所有用户)。我正在研究一个70/30的读/写用例。

我的问题是:坚持这种数据结构最好的选择是什么?我应该考虑构建自己的优化磁盘存储系统吗?否则,是否有一个特定的数据库可以擅长存储这种结构?

2 个答案:

答案 0 :(得分:1)

在关系数据库(例如SqlServer,MySql,Oracle ......)中,表示这种数据结构的典型方式是使用“链接表”。例如:

users table:
userId (primary key)
userName
...

groups table:
groupId (primary key)
...

userGroups table: (this is the link table)
userId (foreign key to users table)
groupId (foreign key to groups table)
compound primary key of (userId, groupId)

因此,要查找名为“fred”的用户的所有组,您可以编写以下查询:

SELECT g.*
FROM users u
JOIN userGroups ug ON ug.userId = u.userId
JOIN groups g ON g.groupId = ug.groupId
WHERE u.name = 'fred'

要实现此结构的原子插入,更新和删除,您必须执行修改事务中各种表的查询。 ORM,例如EntityFramework(用于.NET)通常会为您处理此问题。

答案 1 :(得分:1)

在您进一步阅读之前:不再害怕JOIN 。这是使用Postgres等真正的关系数据库的经典案例。

这有几个原因:

  • 这是为
  • 优化真正的RDBMS
  • 数据库可以理所当然地处理您的完整性约束
  • 这是为
  • 优化真正的RDBMS
  • 你必须推动"加入"逻辑到你自己的代码中
  • 这是为
  • 优化真正的RDBMS
  • 您必须在自己的代码中处理完整性问题
  • 这是为
  • 优化真正的RDBMS
  • 您将最终在自己的代码中重新发明数据库功能
  • 这是为
  • 优化真正的RDBMS

是的,我有点傻,但因为我试图开车回家。

我正在努力敲打这个鼓,因为这是一个经典的案例,有一个随时可用,极其优化的非常稳定的工具,为它定制。

当我说你将重新发明数据库功能时,我的意思是你将开始在你自己的代码中做出基本的数据管理决策。例如,您必须选择何时实际将数据写入磁盘,何时将数据写入磁盘,如何跟踪最高频率的使用数据并将其缓存在内存中(以及如何管理该缓存)等。早期对代码的性能假设可以在不注意的情况下尽早给你的整个代码库带来癌症 - 如果这些假设被证明是错误的,那么稍后更改它们可能需要重大改写。

如果您将数据存储在一个商店中的多对多关系的任意一端,而另一个商店中的多对多地图,则必须:

  1. 在映射的一侧找到初始数据
  2. 提取密钥
  3. 查询多对多处理程序中的密钥
  4. 收到回复集
  5. 根据结果查询与您的其他存储相关的内容
  6. 构建您在系统中使用的答案
  7. 如果您在RDBMS中构建数据以开始代码,则看起来更像是:

    1. 根据您的搜索条件
    2. 运行索引的预建查询
    3. 从回复中建立答案
    4. JOINs 很多比你自己做的更糟糕 - 尤其是在你的ad hoc locate-extract-query-receive-query过程中其他东西可能会发生变化的并发系统中-build过程(当然可以管理,但是为什么在RDBMS设计用来管理它的时候管理它?)。

      JOIN甚至不适合在体面的数据库中运行缓慢。我有一些业务应用程序,它们在相当大的表(几百万行)上不断地连接20个表,并且它们正好通过它们。它针对这种事情进行了高度优化,这就是我使用它的原因。 Oracle在这方面做得很好(但是我无法承受),DB2非常棒(无法承受这一点),SQL Server已经采用了 long 方式(可以&# 39;或者提供那个好的版本!)。另一方面,MySQL的设计考虑了键值存储用例,并且在性能优于其他方面成熟了#34; Web应用程序世界 - 因此它在完整性约束和JOIN方面存在一些问题(但很长时间以来已经很好地处理了复制非常)。因此,并非所有RDBMS都是平等的,但如果不了解您的问题,那么它们就是那种最适合您的数据存储。

      即使是轻微的非平凡数据也会使您的代码在复杂性方面爆炸 - 因此数据库系统的普及。它们不是(应该是)宗教,它们是让你将通用数据处理任务与你自己的程序逻辑分开的工具,所以你不必每个项目重新发明轮子(但无论如何我们倾向于。)

      <强>但是

      问:你什么时候想要这样做?

      答:当你真正构建一个图形而不是一组多对多关系时。

      还有其他类型的数据库专门用于处理该案例。但是,您需要记住您的实际要求。这个数据是短暂的吗?它必须是正确的吗?如果你失去它,你在乎吗?是否需要复制?大多数时间要求都是相对微不足道的,答案是&#34; no&#34;对于这些更高级别的问题 - 如果您有一些特殊的运营需求,那么在做出架构决策时,您可能需要考虑它们。

      如果您一方面存储实际文档(而不是结构化记录)的内容,并且需要在另一方面跟踪它们之间的关系图,那么后端组合可能是个好主意。一些自定义代码粘合在一起的文档数据库+图形数据库可能是正确的。

      仔细考虑您实际面对哪种情况,而不是假设您拥有案例X,因为这是您已经熟悉的。