查看权限通常如何在关系数据库中实现?

Posted

技术标签:

【中文标题】查看权限通常如何在关系数据库中实现?【英文标题】:how are viewing permissions usually implemented in a relational database? 【发布时间】:2010-06-26 05:01:10 【问题描述】:

为项目设置权限的标准关系数据库惯用语是什么?

答案应该是一般的;但是,它们应该能够应用于下面的示例。任何事情都会发生:添加列、添加另一个表——只要它运行良好即可。

应用/示例

假设 Twitter 数据库非常简单:我们有一个 User 表,其中包含登录名和用户 ID;我们有一个Tweet 表,其中包含推文ID、推文文本和创建者ID;我们有一个Follower 表,其中包含被关注的人和关注者的ID。

现在,假设 Twitter 想要启用高级隐私设置(查看权限),以便用户可以准确选择哪些关注者可以查看推文。设置可以是:

Twitter 上的每个人 只有当前的追随者(这当然必须得到用户的批准,但这并不重要)编辑: 像当前一样,我有一个新的追随者,他看到了;我删除了一个关注者,他不再看到它。 特定关注者(例如,用户 ID 5、10、234 和 1) 只有所有者

在这种情况下,表示查看权限的最佳方式是什么?优先级依次是查找速度(您希望能够快速确定要向用户显示哪些推文)、创建速度(您不需要不想花很长时间发布推文),以及有效利用空间(每次我向关注者列表中的每个人发布推文时,我都不应该为每个人添加一行,并且每个追随者我都有一张桌子。)

【问题讨论】:

“答案应该是一般性的;但是,他们应该……”听起来像是从教授的问题中逐字提取的。也许您可以先尝试自己做功课,然后在遇到麻烦时向我们提出具体问题。这不是 RentACoder。 很抱歉,这不是家庭作业——我正在尝试开发一个 Web 应用程序,但对整个 SQL 事物还是很陌生;这个问题困扰我很久了。如果它听起来像一本教科书,我很抱歉——我不是故意那么无聊。 :) 【参考方案1】:

看起来像一个典型的多对多关系——我没有看到任何你想要的限制,这可以节省空间的典型关系数据库习惯用法,即一个有两列的表(都是外国的)键,一个进入用户,一个进入推文)......因为当前的关注者可以并且确实一直在改变,所以向发布时当前的所有关注者发布推文(我假设这就是你的意思?)确实意味着在该关系表中添加许多(极短)行(保留关注者集的时间戳历史的替代方法,以便您可以在任何给定的推文发布时间重建谁是关注者,这在时间而不是在空间上明显更好)。

另一方面,如果您想在查看时(而不是在发帖时)检查关注者,那么您可以制作一个特别的userid 人为地表示“当前用户的所有关注者”(就像您将有一个意思是“Twitter 上的所有用户”);使查找快速所需的 SQL,在这种情况下,看起来很麻烦但可行(一个 UNION 或 OR,带有“我是作者的追随者的所有推文,并且推文可由 [代表的人工用户 ID] 所有追随者读取”)。我不会深入了解 SQL 的那个迷宫,除非你确认这是你心中所想的特殊含义(而不是对我来说似乎更自然但没有的简单含义)允许在关系表上为“向所有关注者发布推文”的操作节省任何空间。

编辑:OP已澄清他们的意思是我在第二段中提到的方法。

然后,假设useridUsers 表的主键,Tweets 表有一个主键tweetid 和一个外键author,用于每条推文作者的用户ID,@987654326 @table 是一个典型的多对多关系表,有两列(外键都变成Usersfollowerfollowee,而Canread 表是一个不那么典型的多对多关系表,仍然有两列——Users 的外键是reader 列,Tweets 的外键是tweet 列(呸;-)。两个特殊用户@everybody@allfollowers 定义为上述含义(因此向所有人、所有关注者或“只是我自己”发帖,都只在Canread 中添加一行——仅选择性发布到特定列表N 个人添加 N 行)。

因此,我认为用户@me 可以读取的一组推文 ID 的 SQL 类似于:

SELECT Tweets.tweetid 
  FROM Tweets
  JOIN Canread ON(Tweets.tweetid=Canread.tweet)
 WHERE Canread.reader IN (@me, @everybody)

UNION

SELECT Tweets.tweetid 
  FROM Tweets
  JOIN Canread ON(Tweets.tweetid=Canread.tweet)
  JOIN Followers ON(Tweets.author=Followers.followee)
 WHERE Canread.reader=@allfollowers
   AND Followers.follower=@me

【讨论】:

对不起,我的模棱两可不好——我的意思是当前的变化。查看更新的问题。 我只是认为在每个帖子中添加这么多行并不是最佳的做事方式; Facebook 有类似的(真正的)能力,我怀疑他们会这样做——如果只是看起来需要做很多工作的话。 @aharon,Facebook 使用关系数据库吗?我想,就像所有流量非常大的网站(包括 Twitter)一样,它们已经加入了 NoSQL 的潮流(正是出于可扩展性的原因)。 Facebook 据说使用了一个巨大的 mysql 集群——至少在 2008 年是这样。有没有你知道的可以更好地处理这种查询/关系的非 sql 数据库? @aharon,是的,有(其中“更好”意味着“更具可扩展性”)——当然,NoSQL DB 总是必须仔细地去规范化以获得最大的性能和可扩展性,其方式各不相同完全在其中,但是 Google 的 Bigtable(不是 App Engine 中暴露的更简单的外观)会对此做出贡献,如果说 Cassandra 做不到,我会感到惊讶(但作为 Google 员工,我的工作是在 bigtable 上,所以这就是我非常熟悉的那个)。不管怎样,看看我上面的 SQL 尝试,对我来说看起来还不错(当然还有所有需要的索引)。

以上是关于查看权限通常如何在关系数据库中实现?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel 关系中实现 SUM()?

JPA中实现双向一对一的关联关系

如何在 PostgreSQL 中实现多对多关系?

如何在 SQL 中实现聚合? (这与 GroupBy 无关)

如何在 Sonata Media Bundle 中实现多对多关系

如何在 Laravel 5.5 中实现多个多对多关系?