不久前,我与同事交谈,他绝对反对使用位掩码,因为很难理解存储在数据库中的所有值。我认为使用它们(例如确定当前用户的角色)并不总是一个坏主意。否则,您需要将其存储在单独的表中,这将导致另一个JOIN。如果我错了,你能告诉我吗?使用位掩码还有其他副作用,优点/缺点吗?
不久前,我与同事交谈,他绝对反对使用位掩码,因为很难理解存储在数据库中的所有值。我认为使用它们(例如确定当前用户的角色)并不总是一个坏主意。否则,您需要将其存储在单独的表中,这将导致另一个JOIN。如果我错了,你能告诉我吗?使用位掩码还有其他副作用,优点/缺点吗?
Answers:
我使用一个使用位掩码存储用户角色分配的应用程序。这是一个痛苦的屁股。如果这使我产生偏见,则被判有罪。
如果您已经在使用关系数据库,则它是一种违反大多数关系理论和所有规范化规则的反模式。当您构建自己的数据存储时,这可能不是一个坏主意。
有太多的表被连接,但是建立了关系数据库来处理这个问题。如果性能成为问题,许多文件将具有附加功能:索引,索引视图等。即使您查找的值不会经常更改,这对Bitmask来说是一个优点,但管理索引的开销是在数据库上非常容易。
尽管数据库在汇总数据方面做得很好,但是当您开始将复杂公式或标量函数之类的内容引入数据集时,它们可能会变得缓慢。您可以在应用程序中按位进行操作,但是如果您所做的只是获取相关数据(查找用户的角色),那么您就无法利用数据存储的最佳性能。
我最后反对这一观点的理由是,对于其他开发人员而言,这很简单。您有用户,角色和分配。这是一个非常常见的多对多关系集(因为存在多个关系),因此应该易于管理。这只是CRUD的东西。
where some_bit_mask & 12 > 0
逐行扫描,就无法搜索行。
user_role_map
或user_priv_map
桌子就足够了。
您已经命名了相关的利弊:
决定做什么需要更多信息:
因此,您要做的就是收集风险因素,然后对它们进行加权,以查看利弊是否超过了利弊。
如果你真的,要真的,真的很紧张的磁盘空间,那么你可能会考虑对用户权限的位图。如果您担心性能,那么请完全不要考虑它们,因为将它们分开实际上会比较慢。您无法有意义地对位映射的字段建立索引,从而导致数据库表扫描,这几乎总是导致性能下降。
除非您是Amazon或Netflix,否则与您拥有的所有其他资源相比,与用户权限有关的数据量可以忽略不计。
任何认真的DBMS都可以处理该“额外加入”而不会闪烁。
使用位掩码的唯一好处是,如果位字段的含义不是静态的。关系表只有在您提前知道记录中每个字段的内容时才能很好地工作:CREATE TABLE
毕竟,您必须在DDL语句中标识这些字段。
如果每个位字段的含义在运行时都是可配置的,或者提前未知,则将布尔值存储为位字段可能有意义。即使这样,它可以定义任意字段的表:field_1
,field_2
,等这给你一个更清洁的关系设计,虽然仍然不理想。由于这两种解决方案都不理想,因此是否优先使用位字段在很大程度上取决于意见。
如果您知道位在开发过程中代表什么,那么请为每个位创建字段并为其赋予有意义的名称。
只是要注意内部平台效果。如果您最终定义了任意但类型良好的字段,那是一回事,但是如果走得太远,您将在关系数据库内部重新创建关系数据库。
我对位掩码很矛盾。我发现他们的大多数批评者都不了解二进制和十六进制。为了清楚起见,请使用良好的助记符。
上面没有提到的一个优点是能够为位掩码添加新含义,而无需花费大量时间来添加新列。我们的数据库设计师(在我之前)将它们放在一个表中,现在每天可获得500万条新记录。添加新列来表示新行为将花费很长时间,而定义新位(我们使用了64中的33)不需要重建表。
不,不能对位掩码进行索引,但是建立33个索引将是荒谬的,并且会减慢对爬网的插入。表搜索使用日期和记录“所有者”索引,因此,如果可能的话,将永远不会使用此位掩码上的索引。