我正在创建我的技术维基站点的第二个版本,我想要改进的其中一个是数据库设计。问题(或者我认为)是要显示每个文档,我需要加入15个表。我有一堆查找表,其中包含与每个wiki条目相关的描述性数据,如程序员使用,cpu,标签,外围设备,PCB布局软件,难度级别等。
以下是布局示例:
doc
--------------
id | author_id | doc_type_id .....
1 | 8 | 1
2 | 11 | 3
3 | 13 | 3
_
lookup_programmer
--------------
doc_id | programmer_id
1 | 1
1 | 3
2 | 2
_
programmer
--------------
programmer_id | programmer
1 | USBtinyISP
2 | PICkit
3 | .....
由于某些文档ID可能具有单个属性的多个条目(例如程序员),因此我创建了数据库来补偿这一点。其他10个属性具有与上面的2 programmer
表类似的布局。要显示单个文档文章,将连接约20个表。
我使用Sphinx搜索引擎查找具有某些特征的文章。本质上,Sphinx会对所有数据进行索引(不存储),并根据显示的过滤器返回感兴趣的Wiki文档ID。如果我想查找使用某个程序员然后按日期排序的文章,MYSQL必须首先将 ALL 文档与2个程序员表连接,然后过滤,最后按插入时间对剩余文件进行排序。没有索引可以帮助我订购过滤结果(需要150,000个文档ID的长时间),因为它是在临时表中完成的。可以想象,随着需要过滤的参数越来越多,它会越来越快。
这是因为我必须依靠Sphinx返回 - 比如所有使用某个CPU和程序员的wiki条目 - 这让我相信我目前的设置有DB气味......
编辑:看起来我已经实现了[实体 - 属性 - 价值模型] 1
答案 0 :(得分:1)
我在这里看不到任何暗示你已实施EAV的内容。相反,看起来你已经为每个表中的每一行分配了一个ID号。这是增加连接数的有保证的方法,它与无与规范化有关。 (没有“我现在添加了一个身份证号码”正常表格。)
选择一个查找表。 (我将在我的例子中使用“programmer”。)不要像这样构建它。
create table programmer (
programmer_id integer primary key,
programmer varchar(20) not null,
primary key (programmer_id),
unique key (programmer)
);
相反,建立它就像这样。
create table programmer (
programmer varchar(20) not null,
primary key (programmer)
);
在引用它的表中,考虑级联更新和删除。
create table lookup_programmer (
doc_id integer not null,
programmer varchar(20) not null,
primary key (doc_id, programmer),
foreign key (doc_id) references doc (id)
on delete cascade,
foreign key (programmer) references programmer (programmer)
on update cascade on delete cascade
);
你获得了什么?您保留了外键引用为您提供的所有数据完整性,您的行更具可读性,并且您已消除了连接。以这种方式构建所有“查找”表,并且每个查找表消除一个连接。 (除非你有数百万行,否则你可能不会看到性能下降。)