构造一个SQL表使其具有匹配项还是返回没有结果更好?
我有一个有趣的设计问题。我正在设计项目的安全性,以允许我们以不同的成本拥有不同版本的程序,并允许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将被允许。