具有可变属性的多个产物范例的数据库计划
我有一个包括差异产物范例的数据库.每种范例都包括互相差别很大的字段.第一类产物分为三类.第二类产物分为三类.但第三个和第四个,没有任何分类. 每种产物可以具有恣意数目的差异属性. 我行使的数据库模子根基上如下: 我有一个复杂的数据库,在产物表中包括约莫500000个产物. 因此,当我要从数据库中获取具有全部属性的产物,可能按属性搜刮产物过滤时,它会严峻影响机能. 任何人都可以辅佐我在sql中的表布局,可能为这个题目做一些索引或任何可行的办理方案.由于差异的电子商务网站正在行使这种数据库而且可以行使大量差异范例的产物. 办理要领您链接的模子看起来像部门 entity–attribute–value(EAV)模子. EAV很是机动,但数据完备性差,并且繁琐且凡是服从低下.它并非真正切合相关模子的精力.在一些大型电子商务网站上事变,我可以汇报你,这不是该规模的尺度或精采的数据库计划实践.假如您没有大量范例的产物(最大都十个,但不是数百个),那么您可以行使两种常用要领中的一种来处理赏罚此题目. 第一种要领是简朴地为产物配置一个表,个中包括每种差异范例产物也许必要的全部属性的列.您可以行使得当每种产物的列,并将别的列留空.假设您贩卖书本,音乐和视频: create table Product ( id integer primary key,name varchar(255) not null,type char(1) not null check (type in ('B','M','V')),number_of_pages integer,-- book only duration_in_seconds integer,-- music and video only classification varchar(2) check (classification in ('U','PG','12','15','18')) -- video only ); 这具有简朴且不必要毗连的利益.可是,它并没有很好地强化数据的完备性(譬喻,你也许有一本没有多个页面的书),假如你有多种范例的产物,那么这个表将变得很是粗笨. 您可以行使表级搜查束缚来办理完备性题目,这些束缚要求每种范例的产物都具有某些列的值,如下所示: check ((case when type = 'B' then (number_of_pages is not null) else true end))) (给Joe Celko提醒 – 我查找了如安在SQL中举办逻辑蕴涵,并找到了一个例子,他用这种布局来构建一个很是相似的搜查束缚!) 你乃至可以说: check ((case when type = 'B' then (number_of_pages is not null) else (number_of_pages is null) end))) 确保没有行在列中的值不得当其范例. 第二种要领是行使多个表:一个基表包括全部产物通用的列,一个帮助表用于每种范例的产物,个中包括特定于该范例产物的列.以是: create table Product ( id integer primary key,name varchar(255) not null ); create table Book ( id integer primary key references Product,number_of_pages integer not null ); create table Music ( id integer primary key references Product,duration_in_seconds integer not null ); create table Video ( id integer primary key references Product,duration_in_seconds integer not null,classification varchar(2) not null check (classification in ('U','18')) ); 请留意,帮助表与主表具有沟通的主键;它们的主键列也是主表的外键. 这种要领如故相等简朴,而且可以更好地执行完备性.但查询凡是涉及毗连: select p.id,p.name from Product p join Book b on p.id = b.id where b.number_of_pages > 300; 完备性如故不美满,由于可以在与主表中的错误范例的行对应的帮助表中建设行,可能在与主表中的单个行对应的多个帮助表中建设行.您可以通过进一步细化模子来办理这个题目.假如您将主键配置为包括范例列的复合键,则产物的范例将嵌入其主键中(书本将具有主键,如(‘B’,1001)).您必要将范例列引入帮助表,以便它们可以具有指向主表的外键,而且您可以在每个帮助表中添加一个搜查束缚,该束缚要求范例正确.喜好这个: create table Product ( type char(1) not null check (type in ('B',id integer not null,primary key (type,id) ); create table Book ( type char(1) not null check (type = 'B'),number_of_pages integer not null,id),foreign key (type,id) references Product ); 这也使得在仅给定主键的环境下查询正确的表更轻易 – 您可以当即汇报它所引用的产物范例,而无需起首查询主表. 可是,如故可以在主表中建设行,而在任何帮助表中都没有对应的行.我不知道怎样办理这个题目. 列存在一再的隐藏题目 – 如上图所示,个中duration列在两个表中一再.您可以通过为共享列引入中间帮助表来办理此题目: create table Media ( type char(1) not null check (type in ('M',id) references Product ); create table Music ( type char(1) not null check (type = 'M'),id) references Product ); create table Video ( type char(1) not null check (type = 'V'),'18')),id) references Product ); 你也许以为不值得支付特另外全力.可是,您也许会思量做的是殽杂行使两种要领(单表和帮助表)来处理赏罚这种环境,并为某些相同的产物提供共享表: create table Media ( type char(1) not null check (type in ('M',classification varchar(2) check (classification in ('U',id) references Product,check ((case when type = 'V' then (classification is not null) else (classification is null) end))) ); 假如在应用措施中将相同的产物齐集在一路,那将出格有效.在这个例子中,假如您的店面一路泛起音频和视频,可是与书本分隔,那么这种布局可以支持比为每种媒体别离行使单独的帮助表更有用的检索. (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |