使用整数作为位域的缺点?

Posted

技术标签:

【中文标题】使用整数作为位域的缺点?【英文标题】:Drawbacks of using an integer as a bitfield? 【发布时间】:2011-03-04 17:23:02 【问题描述】:

对于诸如“可接受的付款类型”之类的东西,我有一堆布尔选项,其中可以包括现金、信用卡、支票、贝宝等。我的数据库中没有六个布尔值,我可以只使用一个整数并为每个付款方式分配一个整数,就像这样

PAYMENT_METHODS = (
    (1<<0, 'Cash'),
    (1<<1, 'Credit Card'),
    (1<<2, 'Cheque'),
    (1<<3, 'Other'),
)

然后查询python中的特定位以检索标志。我知道这意味着数据库无法按特定标志进行索引,但还有其他缺点吗?

我为什么这样做:我已经有大约 15 个布尔值,分成 3 个不同的逻辑“集”。那已经是很多字段了,使用3个多对多表来保存一堆很少会改变的数据似乎效率低下。使用整数允许我为每个字段添加多达 32 个标志,而无需修改数据库。

【问题讨论】:

【参考方案1】:

我能想到的主要缺点是可维护性。对数据库编写查询的人必须了解位约定,而不是能够追求更易读的一组列。此外,如果删除了“接受的付款类型”之一,则必须迁移数据本身,而不仅仅是删除表中的 a 列。

【讨论】:

为什么必须迁移数据?你只是有一个你不会再访问的未使用的位。 删除未使用字段(无论是表示为位还是表示为 db 列)的动机是简化应用程序,从而提高可维护性。不过,你说的很对。即使未移除​​该位,应用程序仍将继续正常运行。【参考方案2】:

这不是最糟糕的,但可能有更好的方法。

定义名为 PaymentTypes 的表

id, paymentId, key (string), value (boolean)

现在您只需在此表中填充您想要的任何内容。没有长的布尔值列,您可以动态添加新类型。这样做的缺点是所有布尔值的默认值都是 NULL 或 false。

【讨论】:

您的意思是为付款类型添加多对多表?我想过……但它是一个额外的层,似乎并没有必要。 @Mark,实际上是一对多,但这有点麻烦。您还可以在带有外键付款的表中有很多布尔列。 @Bryon:为什么会是一对多?每个货件可以接受多种付款方式,每种付款方式可以属于多个货件=m2m。因此是位域而不是简单的枚举。【参考方案3】:

不确定您使用的是什么数据库,但 mysql 有一个 set type。

【讨论】:

不知道这种类型存在。凉爽的!我不认为 Django 支持它。【参考方案4】:

如果您可以将您的用例限制为一组或多组一次只能有一位为真的值,那么您可以在数据库中使用枚举。您将获得两全其美,像 btreat notes 一样可维护,并且比几个布尔值更小(且更简单)。

既然这不可能,我同意你最初的说法并使用位域。但是,我会使用/创建一个位域包装器,这样在您的代码中您就不会直接处理翻转和移位位 - 正如 btreat 所说,这变得难以维护和调试 - 而是像列表或字典一样处理它需要时转换为位域/从位域转换。

Some commentary on enums/bitfields in Django

【讨论】:

(1) 如何使用枚举?枚举存储一个 几个选项(想想单选按钮),而不是几个标志(想想复选框)​​。 (2) Django tag == 对使用什么数据类型没有太多控制。 抱歉,我没有意识到您需要额外的控制。您的示例(付款类型)是单选按钮类型的用法,我对此进行了说明。如果您一次需要多个标志为真,那么枚举确实不起作用。我已经重写了我的答案。 是的......我想这是一个不好的例子。就我而言,用户可以检查不止一种付款类型。我不确定位域包装器是否真的有必要。如果您只是进行一些移位,我发现使用位非常容易。不过,如果我可以为不同的标志命名,而不是记住整数,那会更好。 我给你支票是因为你是唯一一个说“使用位域”的人,这是我最终决定的......虽然我仍然认为这是一个折腾位域和单独的布尔列。实际上......布尔值可能会让每个人的生活更轻松,更容易维护。但是哦,好吧。我不在乎了:'(【参考方案5】:

我认为之前的海报都是正确的。在“关系”数据库中最简洁的方法是定义一个存储支付类型的新关系表。但在实践中,这通常比它的价值更麻烦。

在你的代码中使用枚举并在数据库中使用类似的东西(检查 Oracle 中的约束,AFAIK)应该有助于保持它的可维护性,并且对于那些工作多年后添加新类型的可怜人来说是显而易见的你已经离开了

【讨论】:

以上是关于使用整数作为位域的缺点?的主要内容,如果未能解决你的问题,请参考以下文章

c语言 关于位域的使用

零长度位域的实际使用

零长度位域的实际使用

从Nginx源码中学习C语言位域的使用DaemonCoder

C语言 | 位域的使用详解

关于位域在结构体的应用