在MySQL中,在一个表中有500列是否很好?

时间:2017-08-10 10:21:01

标签: mysql database-design database-administration entity-attribute-value

在MySQL中,在一个表中有500列是否很好? 行将每天增加,最大行数将小于或等于1百万。

只是简单介绍一下,这些是我的列标题

TableName:process_detail id, process_id, item_id, item_category, attribute1,attribute2,attribute3,...,attribute500,user_id1_update_time,user_id2_update_time,user_id1_comments,user_id2_comments

所有属性都是varchar,长度最大为30.但小于30。

我有25个item_categories。

我应该创建一个像'process_detail'这样的单个表,还是应该按类别创建多个表,如category1_process_detail,category2_process_detail,..,category25_process_detail

每个item_category有不同的列数,有些列有200列,有些列只有50列。假设category1将有200列,category2将有50列。

category1中的某些列不属于category2。

process_id1中的

item_ids可能位于process_id2中。在良好的表现方面,最好的方法是什么?请adivce。

2 个答案:

答案 0 :(得分:1)

不,这不是一个好主意。而是使用多对一关系映射。

例如,按照您的建议创建process_detail表,但不包含属性列。然后创建另一个表process_detail_attributes

CREATE TABLE `process_detail_attributes`  
(`pda_id` INT NOT NULL AUTO_INCREMENT,  
 `id` INT NOT NULL,   
 `attribute_key` INT NOT NULL,  
 `attribute_value` VARCHAR(30) NOT NULL,  
  PRIMARY KEY(`pda_id`),  
  FOREIGN KEY (id) REFERENCES process_detail (id)
) ENGINE...

然后对于每个属性(attribute1...attribute500),只需在属性表中输入一行,并在外键列中插入相应的id。

这样做的好处很多。 Doomenik提到的链接可能是理解其中的一个很好的起点,但简而言之......

- 如果没有使用所有属性,就不会浪费存储空间 - 即使使用了属性,数据也将存储在实际的索引B-Tree节点中,过度膨胀每页数据量并减少能够适应缓冲池(即RAM)的页面数量并减少钥匙的位置。这将随后减慢索引遍历的速度 - 如果这些属性需要索引(通常这些属性),那么这个表的不灵活将是不合情理的。

当然,为了提高性能,你可以考虑去标准化,但这似乎不是其中之一。

然后,您可以从process_detail中选择包含所有属性的数据,如下所示:

SELECT a.process_id,  
a.user_id1_u‌​pdate_time,  
a.user_id2_u‌​pdate_time,  
a.user_id1_comments,  
a.user_id2_comments,  
b.*  
FROM process_detail a INNER JOIN process_detail_attributes b  
WHERE a.id = b.id AND whatever_condition_you_want_to_filter_by_here;

答案 1 :(得分:0)

InnoDB不支持500 varchar列,因为存储了行的方式。即使您使用InnoDB的ROW_FORMAT=DYNAMIC,这将为varchars每行存储500x20字节,这将大于8KB行大小限制。有关InnoDB行存储的详细信息,请参阅https://www.percona.com/blog/2010/02/09/blob-storage-in-innodb/

拥有如此大量的列无论如何都是有问题的数据库设计的红旗。

  • 如果您为类似属性存储了大量列,则违反了eliminating Repeating Groups of columns的原则,这是使表格满足第一范式的一部分。

  • 如果列不是类似的属性,那么您根本就不是设计关系。在关系中,您必须使用有意义的列名和数据类型定义标题。当您将列命名为attribute1等时,您并不是以关系方式设计表格。

我不同意使用EAV表设计的建议。我经常在Stack Overflow或我的博客EAV FAIL上发布关于EAV是关系数据库的破坏设计的事实。

请参阅我对https://stackoverflow.com/a/695860/20860或我的演示文稿Extensible Data Modeling的回答,了解为不同流程类型存储不同属性的任务的替代解决方案。

您可能希望了解如何使用MySQL 5.7中的JSON data type来存储特定于每种不同流程类型的半结构化属性集合。