PostgreSQL - 管理用户的联系人 - 更好的单向或双向关系?

时间:2015-10-01 10:28:51

标签: performance postgresql jpa eclipselink user-management

我正在研究如何使用Vaadin + JPA + EclipseLink + PostreSQL开发用于共享图片的Web应用程序,以及这种组合如何适合此目的。我正在努力做出有关用户联系人管理的决定。在解释表格的结构后,我将进一步详细说明:

用户表

users表包含以下列:

  • 用户ID - 在注册时自动生成(唯一)
  • 用户名 - 用户名;注册时定义(唯一)
  • 密码 - 用户的密码;在注册时定义
  • 上传 - 用户上传的所有图片ID。我不会在这里详细说明,因为这并不关心我的问题。可以说此列与另一个名为图像的表一起用于管理当前用户的图库

通讯录表

这张表纯粹是为了存储用户之间的关系信息(我的一位同事决定这样做,我坦白地说不喜欢,但它已经完成了......)。它只有两列:

  • 用户ID - 拥有联系人的用户ID(见下文)
  • 通讯录 - 存储用户ID 的用户有权查看其图片库的所有用户ID。

    注意:这是不是双向关系。这意味着当用户X将用户Y添加到他的联系人时,用户X将访问他的自己的图像库授予用户Y.但是,这不会使用户Y对用户X可见。只有当用户Y还将用户X添加到他的联系人时,才会发生这种情况。图像可以是公共的也可以是私有的。所有用户都可以查看公共图像,但是私有用户只能由拥有这些图像的用户以及所有者通过将其添加到其联系人而授予访问权限的所有其他用户来查看。 "私人"可能不是这里最好的术语,所以你可以将其视为"允许朋友查看它"有点像。

每当我删除用户时,我都必须执行以下操作:

  1. 删除用户上传的所有图片文件 - 图片表中的图片只有一个上传者。查看状态完全安全,只需删除文件并从图像表中删除其条目,因为每个图像都绑定到其上传者而没有其他人(受影响:图像 table,storage)
  2. 删除用户的文件夹 - 遗憾的是,Java的工作方式必须首先确保文件夹在删除之前是空的(受影响的:存储)
  3. 从所有用户的所有联系人列表中删除用户 - 此处是我遇到的主要困境(受影响:用户表)
  4. 自行删除用户(受影响:用户表格)
  5. 由于我到目前为止所写的查询,这个命令基本上是应该如何。考虑到我的表之间的关系,我发现它是最佳的。

    正如我在 3 中提到的那样,我在如何以尽可能少的努力(编码和性能)方面做到了这一点。我正在研究两种解决方案:

    • 单向关系 - 不要更改用户表,只需遍历其中的所有用户,然后遍历查找每个用户的联系人我要删除的当前用户的用户ID

    • 双向关系 - 向名为 addedBy 用户添加新列,该列存储已添加当前用户的所有用户ID我要删除其联系人的用户。每当用户X将另一个用户添加到他的联系人时,该另一个用户就会添加"用户X到 addedBy 列表但不是联系人

    我在单向关系中看到的问题正是我必须遍历所有用户,然后检查每个用户的联系人以查看它是否包含用户ID想要删除。

    我在双向关系中看到的问题是随新列添加的开销。然而,最重要的是我可以跳过查看所有用户的联系人(当然最糟糕的情况是用户已被添加到所有用户的联系人中,而这些用户很可能不会发生;))并且只做这个对于那些在 addedBy 列表中的人。

    我远离数据库专家,您可能已经从上面的书面中注意到,可能有更好的做事方式。但是,我只对上面提到的两个版本感兴趣,并且对数据库的更改尽可能少。此外,我不知道哪个查询更容易编写。我已经成功完成了删除过程中的所有其他步骤(1,2和4),但是第3步是一个艰难的步骤。

    知道哪一个更好?用户数量并不重要,因为这完全是为了研究而完成的,但用户表中的几百/千个条目应该会使事情变得更加真实。

1 个答案:

答案 0 :(得分:1)

我认为你的同事有一些正确的方法,但没有全力以赴。

" Contacts表",此表看起来像一个多对多关系表。

但问题是你所描述的:

  

联系人 - 存储具有用户ID的用户提供的所有用户ID   允许查看他的图片库。

在真正的多对多关系表中,您将有两列

  • ' user_id',您已有的

  • ' contact_user_id' (命名可能会有所不同)但主要的一点是,每个联系人在此表中只有一行。

因此,当您删除用户并希望从所有联系人列表中删除此用户时,您只需说:

delete from Contacts where contact_user_id = :userIdOfUserToBeDeleted

正如@Predrag Maric所描述的那样,这将使您的数据库数据更加健康,不仅在user_id上引用完整性,而且还链接了contact_user_id。

如果您使用JPA或类似功能,这也会有所帮助,您可以使用JPA进行删除策略,您可以将其设置为级联以删除这些引用。但这仅在完全标准化的表中得到支持。