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 | 4
6或当我想要返回特定用户可以看到的新闻帖子时,我可以使用类似的查询.
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的所有权限.
缺点:难以写入数据,难以读取数据,难以调试,尤其是:查询速度慢,因为数据库无法对此类查询使用索引.
优点,你节省了几个字节.与BIT字段相比,您可以在一百万个记录表上节省几MB ...几乎不值得.:)
如果您只有少数角色,则甚至不会在PostgreSQL中保存任何存储空间.一列使用4个字节,一个8字节.两者都可能需要对齐填充:integer
bigint
一boolean
列使用1个字节.实际上,您可以为一integer
列配置四个或更多布尔列,为一个列配置八个或更多bigint
.
单个列更易于阅读和索引.其他人已经就此发表了评论.
您仍然可以利用表达式或部分索引上的索引来规避索引问题("非可搜索").广义陈述如:
数据库不能像这样在查询上使用索引
要么
这些条件是非SARGable!
是不完全正确的 -也许对一些人缺乏这些功能RDBMS.
但是,为什么要避开这个问题呢?
正如你已经澄清的那样,我们正在谈论6种不同的类型(可能更多).单独boolean
列.与一个相比,你甚至可能节省空间bigint
.在这种情况下,空间要求似乎并不重要.
如果这些标志是互斥的,您可以使用一列类型enum
或一个小型查找表和一个引用它的外键.(排除了问题更新.)
这里至少有一个巨大的劣势......
这些条件是非SARGable!
这是一个很大的问题,对我来说这将是一个破坏者.您需要执行的按位评估(据我所知)在任何数据库中都不可索引 - 引擎需要检查每一行以执行评估,这意味着可怕的性能.
归档时间: |
|
查看次数: |
8899 次 |
最近记录: |