数据库列中位标志的任何缺点?

ams*_*ams 10 sql sql-server oracle postgresql database-design

请考虑以下表格:

CREATE TABLE user_roles(
    pkey         SERIAL PRIMARY KEY,
    bit_id       BIGINT NOT NULL,
    name         VARCHAR(256) NOT NULL,
);

INSERT INTO user_roles (bit_id,name) VALUES (1,'public');
INSERT INTO user_roles (bit_id,name) VALUES (2,'restricted');
INSERT INTO user_roles (bit_id,name) VALUES (4,'confidential');
INSERT INTO user_roles (bit_id,name) VALUES (8,'secret');

CREATE TABLE news(
    pkey          SERIAL PRIMARY KEY,
    title         VARCHAR(256),
    company_fk    INTEGER REFERENCES compaines(pkey), -- updated since asking the question
    body          VARCHAR(512),
    read_roles    BIGINT -- bit flag 
);
Run Code Online (Sandbox Code Playgroud)

read_roles是一个位标志,指定可以读取新闻项的某些角色组合.因此,如果我插入一个可以通过限制和机密读取的新闻项目,我会将read_roles设置为值为2 | 46或当我想要返回特定用户可以看到的新闻帖子时,我可以使用类似的查询.

select * from news WHERE company_fk=2 AND (read_roles | 2 != 0) OR  (read_roles | 4 != 0) ; 
select * from news WHERE company_fk=2 AND read_roles = 6; 
Run Code Online (Sandbox Code Playgroud)

一般来说,在数据库列中使用位标志有什么缺点?我假设这个问题的答案可能是数据库特定的,所以我有兴趣了解特定数据库的缺点.

我正在使用Postgres 9.1作为我的应用程序.

更新我得到了一些关于数据库的信息,而不是使用索引进行位操作,这需要进行全表扫描才能获得性能.所以我更新了问题以更密切地反映我的情况,数据库中的每一行都属于一个特定的公司,因此所有查询都将包含WHERE子句,其中包含一个将在其上有索引的company_fk.

更新我现在只有6个角色,将来可能更多.

UPDATE角色不是互斥的,并且它们彼此继承,例如,restricted会继承分配给public的所有权限.

Gol*_*rol 9

缺点:难以写入数据,难以读取数据,难以调试,尤其是:查询速度慢,因为数据库无法对此类查询使用索引.

优点,你节省了几个字节.与BIT字段相比,您可以在一百万个记录表上节省几MB ...几乎不值得.:)


Erw*_*ter 8

如果您只有少数角色,则甚至不会在PostgreSQL中保存任何存储空间.一列使用4个字节,一个8字节.两者都可能需要对齐填充:integerbigint

boolean列使用1个字节.实际上,您可以为一integer列配置四个或更多布尔列,为一个列配置八个或更多bigint.

还要考虑到NULL值只在NULL位图中使用一位(简化).

单个列更易于阅读和索引.其他人已经就此发表了评论.

您仍然可以利用表达式部分索引上的索引来规避索引问题("非可搜索").广义陈述如:

数据库不能像这样在查询上使用索引

要么

这些条件是非SARGable!

不完全正确的 -也许对一些人缺乏这些功能RDBMS.
但是,为什么要避开这个问题呢?

正如你已经澄清的那样,我们正在谈论6种不同的类型(可能更多).单独boolean列.与一个相比,你甚至可能节省空间bigint.在这种情况下,空间要求似乎并不重要.


如果这些标志是互斥的,您可以使用列类型enum或一个小型查找表和一个引用它的外键.(排除了问题更新.)


JNK*_*JNK 6

这里至少有一个巨大的劣势......

这些条件是非SARGable!

这是一个很大的问题,对我来说这将是一个破坏者.您需要执行的按位评估(据我所知)在任何数据库中都不可索引 - 引擎需要检查每一行以执行评估,这意味着可怕的性能.

  • 显然,可以为按位操作创建部分索引:http://stackoverflow.com/questions/9226217/bitwise-operations-in-postgres (2认同)