构造一个SQL表使其具有匹配项还是返回没有结果更好?

时间:2020-03-05 18:42:15  来源:igfitidea点击:

我有一个有趣的设计问题。我正在设计项目的安全性,以允许我们以不同的成本拥有不同版本的程序,并允许Manager型用户向其他用户授予或者拒绝对程序部分的访问。它将基于Web并托管在我们的服务器上。

我为每个"资源"或者屏幕使用一个简单的"允许"或者"拒绝"选项。

我们将拥有大量资源,并且用户将能够建立许多不同的组来让用户控制访问。每个用户只能属于一个组。

我想到了两种方法,并且很好奇,这对于SQL Server在性能方面会更好。

选项A
访问表中存在条目表示允许访问。这将不需要数据库中的列来存储信息。如果没有返回结果,则拒绝访问。

我认为这将意味着表较小,但是查询会搜索整个表以确定是否没有匹配项吗?

选项B
数据库中包含一个控制"允许/拒绝"的位列。这将意味着总会找到结果,并且会产生更大的表。

有什么想法吗?

解决方案

回答

我会投票给选项B。如果我们选择选项A,并且假设用户存在,那么他们就可以进入,那么最终我们将遇到一个问题,即我们想拒绝对用户的访问而不会删除用户记录。

在很多情况下,我们都希望将用户锁定在外,但又不想完全销毁他们的帐户。其中一种情况(不一定与用例相关联)是我们无法付款时,他们切断了帐户,直到我们再次开始付款为止。他们不想删除记录,因为他们仍然想在我们再次付款时启用该记录,而不是从头开始创建帐户并丢失所有用户历史记录。

回答

B.它可以更好地检查数据是否完整(例如,当我们添加允许/拒绝功能时)。

此外,表大小仅应考虑到我们知道将包含许多记录(如100,000+)的表。我们甚至花时间在这个问题上键入表格大小的考虑,已经比花费额外的硬盘空间花费更多。

回答

如果只允许/拒绝,那么在用户和资源之间建立一个简单的链接表就可以了。如果在链接表中有一个键入用户资源的条目,则允许访问。

UserResources
-------------
UserId FK->Users
ResourceId FK->Resources

和SQL将是这样的

if exists (select 1 from UserResources 
where UserId = @uid and ResourceId=@rid)
set @allow=1;

使用(UserId和ResourceId)上的聚集索引,即使有数百万条记录,查询也将非常快。

回答

方法A,但除隐式拒绝外,我还将明确拒绝。我会用一些用例来确保最终逻辑有效,但这是一些示例。

User1 is in group1 and group2.  
User2 is in group1  
User3 is in group2
Folder1 allows group1 and deny group2.  
User1 is denied.  
User2 is allowed.  
User3 is denied.

我相信方法users1将被允许。