数据库气味 - 使用多个表改进当前设计

时间:2012-09-07 23:45:12

标签: mysql database-design

我正在创建我的技术维基站点的第二个版本,我想要改进的其中一个是数据库设计。问题(或者我认为)是要显示每个文档,我需要加入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

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
);

你获得了什么?您保留了外键引用为您提供的所有数据完整性,您的行更具可读性,并且您已消除了连接。以这种方式构建所有“查找”表,并且每个查找表消除一个连接。 (除非你有数百万行,否则你可能不会看到性能下降。)