2017-02-22 7 views
0

Итак, я создаю базу данных в MySQL, которая содержит приблизительно 20 000 таблиц, по одному для каждого человеческого гена, где в таблице каждого гена есть один столбец с перечислением альтернативных имен (синонимов) для этого гена, найденного в в литературе, и часто, когда нет логики для этих синонимов, и они существуют исключительно по историческим причинам.База данных MySQL с тысячами таблиц

Прежде всего, есть ли лучший способ настроить эту базу данных с меньшим количеством таблиц?

Проблема состоит в том, что каждый ген имеет переменное количество альтернативных имен, поэтому я не могу сделать одну большую таблицу с каждой строкой, соответствующей генам и количеству столбцов. И даже если у каждого гена было такое же количество альтернативных имен, любой конкретный столбец в принципе был бы бессмысленным, поскольку, например, не было бы никакой связи между синонимом в столбце 1 для гена 1 и синонимом в столбце 1 для гена 2.

Что именно плохого имеет тысячи таблиц в MySQL?

Я могу потенциально разбить базу данных на 23 базы данных (по одной для каждой хромосомы) или что-то в этом роде, и тогда каждая база данных будет иметь только 900 таблиц, было бы лучше?

Я почти чувствую, что, возможно, MySQL (реляционная база данных) является неправильным инструментом для работы. Если это так, то какая была бы лучшая парадигма базы данных?

+6

Я бы создал одну таблицу «ген», а затем другую таблицу «чередует» с идентификатором гена в качестве внешнего ключа. – Jaime

+0

@Jaime Вы имеете в виду одну глобальную таблицу «чередующихся» для всех генов? А затем использовать внешний ключ для определенного гена для поиска связанных с ним синонимов в этой «альтернативной» таблице? – Thoth

+0

И один стол для хромосом. –

ответ

2

20 000 столов - это много столов. Нет ничего плохого в том, что у вас 20 000 таблиц, если у вас действительно есть 20 000 таблиц. Мы запускаем с innodb_file_per_table, так что это целая куча файлов, и мы потенциально столкнемся с некоторыми ограничениями в MySQL (innodb_open_files, open_files_limit, table_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'); 

И запрос, вместо того, чтобы выяснить, из каких из 20 000 таблиц будут запрошены, мы запросили бы только один стол и включили условие на gene столбец:

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' 

Чтобы сделать тот же поиск с 20000 таблиц, мне нужно было 20000 различных сортирует, по одному для каждого каждого из 20 000 таблиц.

Я просто взял swag на типы данных. Поскольку у MySQL есть ограничение на 64 символа для имени таблицы, я ограничил столбец gene до 64 символов.

Мы можем заполнить столбцом гена именами таблиц в текущем проекте.

Однако эта таблица не может эмулировать пустую таблицу, ген, который не имеет синонимов. (Или, может быть, наш проект будет для названия гена быть синонимом себя, поэтому мы имеем ряд ('alzwhatever','alzwhatever')

В любом случае, мы бы, вероятно, также хотят, чтобы добавить таблицу, как это:

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

Это таблица, которая будет иметь 20000 строк, одна строка для каждой из таблиц в текущем проекте.

Кроме того, мы можем добавить ограничение внешнего ключа

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

Этот дизайн намного больше соответствует нормативной структуре реляционных баз данных.

Это не означает, что другие конструкции являются «плохими». Только этот дизайн будет более типичным.

+0

Спасибо за отличный ответ! У меня было несколько вопросов, во-первых, каково значение 'gs' в ваших 3-м и 4-м блоках кода? Кажется, он ничего не делает, и я могу оставить его, и все работает одинаково. Во-вторых, не могли бы вы объяснить свой последний блок кода с помощью ограничения внешнего ключа? Какова эксплуатационная полезность добавления этого? Благодарю. – Thoth

+0

В запросах «gs» - это псевдоним короткой таблицы, назначенный для ссылки на таблицу. В этом случае псевдоним не требуется. В других более сложных запросах нам нужно вводить псевдонимы. Но мы квалифицируем * все * ссылки столбцов, а использование псевдонимов в коротких таблицах - это правильный шаблон, с которым мы хорошо знакомы. Тот же шаблон просто переносится на более простые запросы, даже если это не требуется. Ограничение внешнего ключа является механизмом обеспечения согласованности. Он не позволяет присваивать значения столбцу «gene» в таблице «gene_synonym», которые не отображаются в таблице «gene». – spencer7593

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

Тогда у вас есть одна строка для каждого синонима для всех генов в одной таблице.

Что плохого в том, чтобы иметь тысячи столов? Вот несколько вещей:

  • Хранилище данных очень неэффективно. Минимальное пространство, занимаемое таблицей, является страницей данных. Если вы не заполняете страницу, вы теряете пространство.
  • Потеряв пространство, вы в конечном итоге заполняете кеш страницы почти пустыми страницами. Это означает, что меньше данных вписывается в память, что отрицательно сказывается на производительности.
  • Ваши запросы жестко привязаны к доступной таблице. Вы не можете написать общий код для нескольких генов.
  • Вы не можете легко вносить изменения в свою структуру данных.
  • Вы не можете проверить данные, указав, что «синоним должен быть уникальным во всех генах».
  • Вы не можете легко найти ген, к которому относится синоним.
  • Улучшение производительности, например, добавление индексов или разбиение данных - это кошмар.