我需要一些建议来选择我的表结构。
我正在开展一个项目,我需要保存值,这些值是可变数量的其他值的组合。
例如:
A = b,c,d
B = z,r
我正在考虑将组合保存在列中的json对象中,但我担心它对于大请求来说可能很长并且不容易过滤。
还有一个具有多个列的解决方案(在不需要时包含null),但这不是数据的良好表示,过滤也很难。
最后我认为最好的关系是多对多,但加入可能太重了,是吗?
您是否看到任何其他替代方案(除了切换到nosql)?
答案 0 :(得分:0)
这显示了使用Junction表来避免在逗号分隔的列表,json或其他至少在以下方面存在问题的机制中保存数据:
create table cat
( -- categories
id int auto_increment primary key,
code varchar(20) not null,
description varchar(255) not null
);
create table subcat
( -- sub categories
id int auto_increment primary key,
code varchar(20) not null,
description varchar(255) not null
);
create table csJunction
( -- JUNCTION table for cat / sub categories
-- Note: you could ditch the id below, and go with composite PK on (catId,subCatId)
-- but this makes the PK (primary key) thinner when used elsewhere
id int auto_increment primary key,
catId int not null,
subCatId int not null,
CONSTRAINT fk_csj_cat FOREIGN KEY (catId) REFERENCES cat(id),
CONSTRAINT fk_csj_subcat FOREIGN KEY (subCatId) REFERENCES subcat(id),
unique key (catId,subCatId) -- prevents duplicates
);
insert cat(code,description) values('A','descr for A'),('B','descr for B'); -- id's 1,2 respectively
insert subcat(code,description) values('b','descr for b'),('c','descr for c'),('d','descr for d'); -- id's 1,2,3
insert subcat(code,description) values('r','descr for r'),('z','descr for z'); -- id's 4,5
-- Note that due to the thinness of PK's, chosen for performance, the below is by ID
insert csJunction(catId,subCatId) values(1,1),(1,2),(1,3); -- A gets a,b,c
insert csJunction(catId,subCatId) values(2,4),(2,5); -- B gets r,z
以下错误是好的和预期的,数据保持清洁
insert csJunction(catId,subCatId) values(2,4); -- duplicates not allowed (Error: 1062)
insert csJunction(catId,subCatId) values(13,4); -- junk data violates FK constraint (Error: 1452)
为了回应您的评论,数据仅在mysql具有最近使用(MRU)策略时缓存,不超过或少于内存中缓存的任何数据与物理查找。
B
目前不仅可能包含z,r
,而且 还可以包含c
,A
也是如此并不意味着重复。并且如模式所示,没有父级可以复制其对子级的包含(或重复),这无论如何都会成为数据问题。
请注意,可以使用code
列轻松地在cat和subcat中使用PK的路径。遗憾的是,这会导致广泛的索引,甚至是联结表的更复杂的索引。这将大大减缓运营速度。虽然数据维护在视觉上可能更具吸引力,但我任何时候都会performance
过appearance
。
当时间允许显示“"什么类别包含某个子类别",删除等”时,我将添加到此答案