包含数千个表的MySQL数据库

时间:2017-02-22 22:08:39

标签: mysql sql database

所以我在MySQL中构建一个数据库,其中包含大约20,000个表,每个人类基因一个,每个基因的表有一个列,列出了该基因的替代名称(同义词)。文献,往往没有这些同义词的逻辑,它们纯粹出于历史原因而存在。

首先,是否有更好的方法使用更少的表设置此数据库?

问题在于每个基因都有可变数量的替代名称,因此我不能制作一个大表,每行对应一个基因和一定数量的列。即使每个基因具有相同数量的替代名称,任何特定的列基本上都是无意义的,因为例如,基因1的第1列中的同义词与基因2的第1列中的同义词之间没有关系。

在MySQL中拥有数千个表究竟有什么不好?

我可能会将数据库分成23个数据库(每个染色体一个),或类似的东西,然后每个数据库只有~900个表,这会更好吗?

我几乎觉得MySQL(关系数据库)可能是错误的工具。如果是这样,那么什么是更好的数据库范例呢?

2 个答案:

答案 0 :(得分:2)

你应该有一个同义词表。 一个这样的表:

create table geneSynonyms (
    geneSynonymId int auto_increment primary key,
    geneId int not null,
    synonym varchar(255),
    constraint fk_geneSynonyms_geneId foreign key (geneId) references genes(geneId),
    constraint unq_geneSynonyms_synonym unique (synonym)  -- I assume this is unique
);

然后,对于单个表中的所有基因,每个同义词都有一行。

拥有数千张桌子有什么不好?以下是一些事项:

  • 数据存储效率非常低。表占用的最小空间是数据页。如果你没有填写页面,那就是在浪费空间。
  • 通过浪费空间,您最终会用几乎空的页面填充页面缓存。这意味着更少的数据适合内存,这会对性能产生负面影响。
  • 您的查询已硬连接到正在访问的表。你不能为多个基因编写通用代码。
  • 您无法轻松更改数据结构。
  • 您无法通过规则说“同义词在所有基因中都是唯一的”来验证数据。
  • 您无法轻易找到同义词所指的基因。
  • 通过添加索引或分区数据来提高性能是一场噩梦。

答案 1 :(得分:2)

20,000个表是很多表。没有必要"坏"关于拥有20,000桌子,如果你真的需要20,000桌子。我们使用innodb_file_per_table运行,因此这是一大堆文件,我们可能会遇到MySQL中的某些限制(innodb_open_filesopen_files_limittable_cache_open)反过来又受操作系统ulimit限制。

除此之外,管理大量相同表的潜在困难。如果我需要添加一列,我需要将该列添加到20,000个表中。这是20,000个ALTER TABLE语句。如果我错过了一些桌子,桌子就不再相同了。如果我可以帮助的话,我只是不想去那里。

我建议并考虑不同的设计。

作为第一个剪辑,如:

CREATE TABLE gene_synonym
( gene           VARCHAR(64) 
, synonym        VARCHAR(255)
, PRIMARY KEY (gene, synonym)
) ENGINE=InnoDB
;

添加基因的同义词,而不是将值插入特定表的单个列中:

INSERT INTO gene_synonym (gene, synonym) VALUES ('alzwhatever','iforgot');

在查询时,我们只查询一个表,并在gene列上包含一个条件,而不是查明哪些20,000个表是查询:

SELECT gs.synonym 
  FROM gene_synonym gs
 WHERE gs.gene = 'alzwhatever'
 ORDER BY gs.synonym

WHERE子句使得我们可以查看一个大表的子集,返回的集合将模拟当前单个表中的一个。

如果我需要搜索同义词,我可以查询这一个表:

SELECT gs.gene
  FROM gene_synonym gs
 WHERE gs.synonym = 'iforgot'

要使用20,000个表进行相同的搜索,我需要20,000个不同的SELECT,每个20,000个表一个。

我只是对数据类型进行了抨击。由于MySQL对表名的限制为64个字符,因此我将gene列限制为64个字符。

我们可以使用当前设计中的表名来填充基因列。

然而,这个表无法模仿的是一个空表,一个没有任何同义词的基因。 (或者我们的设计可能是因为基因的名称是它自己的同义词,所以我们有一行('alzwhatever','alzwhatever')

无论哪种情况,我们都可能想要添加这样的表:

CREATE TABLE gene
( gene           VARCHAR(64) 
, PRIMARY KEY (gene)
) ENGINE=InnoDB
;

这是包含20,000行的表,当前设计中每个表都有一行。

此外,我们可以添加外键约束

ALTER TABLE gene_synonym 
ADD CONSTRAINT FK_gene_synonym_gene (gene) REFERENCES gene (gene)
  ON UPDATE CASCADE ON DELETE CASCADE
;

这种设计更符合关系数据库的规范模式。

这并不是说其他​​设计是"坏"。只是这种设计会更典型。