【问题标题】:Bitmasks vs. separate columns位掩码与单独的列
【发布时间】:2013-05-03 16:38:49
【问题描述】:

我有一个用户数据库和他们的权限。例如,一行如下所示:

    Name    | sendMessages | receiveMessages | post | readPosts
------------+--------------+-----------------+------+----------
Jeff Atwood |      1       |        1        |  0   |     1

对于这种情况有什么更好的方法,单独的列(如示例中所示)或包含位掩码的单个列(在这种情况下,1101 转换为 0xD)?

【问题讨论】:

  • 出于查询目的,绝对要分开列。除非存储空间是一个实际的现实问题,否则我会同意
  • 如果您认为您将拥有比您的掩码列更多的权限,事情可能会变得非常丑陋。如果每个权限有一栏,它也可能更容易阅读。我肯定会使用单独的列

标签: mysql


【解决方案1】:

tinyint(1) 作为布尔值通常是最好的方法。

使用位掩码进行查询效率不高,因为如果必须计算它就不能使用索引 或者如果你尝试使用索引会变得非常讨厌

让我们看看简单的查询

select * from tbl where sendMessages = 1 and readPosts = 1

单列是:

select * from tbl where val&9 = 9

这不是很有效,因为它必须进行全表扫描和计算。

让我们尝试重写查询,以便它可以使用索引。 这可以通过使用IN 列出所有可能的值来完成:

select * from tbl where val in (9, 11, 13, 15)

现在想象一下,如果你想做简单的where readPosts = 1,这个查询会是什么样子

但是,如果你列出的值太多,mysql 优化器仍然会进行全表扫描

【讨论】:

  • 此规则的例外情况是,如果您有成百上千的未直接查询的位。
  • 感谢您的评论。总是有例外。对于 n = 数百或数千,您需要多少列? n/64?
  • 如果它是每个“位”一列,那么大概与您的位一样多的列。在某些时候,您的架构不再有意义。
  • 如果这些位字段的使用率很低,如果它们的使用很少,那将是有意义的。
【解决方案2】:

不使用列作为权限,而是创建一个权限表和一个用户权限链接表呢?

【讨论】:

  • 我没有看到优势。
  • @Giulio 它允许在不更改数据模型的情况下添加、修改和删除权限。它使查询更容易,您不必更改列名,但可以更改传递给 WHERE 子句的参数。以及标准化的许多其他好处。
  • @GiulioMuscarello 请参阅:stackoverflow.com/questions/9774715/… 每种方法各有利弊。使用权限/角色通常可以安全地应用规范化实践。当您开始超过 40,000 条规范化记录时,在连接操作期间,您通常会遇到查询时间的增加。
【解决方案3】:

最好将权限存储为具有 BIT 数据类型的单独列。大多数现代数据库引擎优化位列存储:

  • 对于一个表中最多 8 位的列,这些列存储在 1 个单字节中。
  • 对于 9 位和最多 16 位的列,这些列存储在 2 个字节中,
  • 等等

因此,它充分利用了您列出的两个选项。通过位掩码需要更少的存储空间,同时保持多列的清晰度。引擎会为您处理。

【讨论】:

    【解决方案4】:

    使用位掩码您不能使用第一个或最后一个位 0 和(32 投注中的 31 / 64 位中的 63 ???)但可以使用 pow(2, bit) & field = pow(2, bit )

    如果您需要超过 1 个可以处理的字段,那么您必须开始使用多个字段,然后您会陷入弄清楚您的位设置在哪个字段中的痛苦。

    这可以通过一个简单的例程轻松克服,根据您要查找的位和相关的字段或行返回真或假。

    但是对于权限,最好就像@CodeCaster 所说的那样使用权限表和链接表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-08
      • 2018-04-28
      • 1970-01-01
      相关资源
      最近更新 更多