Проблема
У нас есть быстро растущая база данных с несколькими большими таблицами соединений (в настоящее время в миллиардах строк), но по мере роста этих таблиц время запроса сократилось. Проблема заключается в том, что по мере добавления большего количества данных в таблицы, связанные этими таблицами соединений, таблицы соединений будут продолжать расти более быстрыми темпами и отрицательно влияют на скорость запросов.
Фон
Я имею дело с базой данных, которая хранит геномную информацию. Ряд маркеров (~ 3 миллиона), соответствующих локусам, в которых имеются вариации ДНК, связаны с индивидуумами, чей генотип определен в этих локусах. Каждый маркер имеет ряд возможных генотипов, из которых каждый должен иметь один.
Текущая реализация
Когда база данных (postgresql) была еще небольшой, не было проблем с привязкой генотипов к маркерам с использованием внешних ключей, а затем с привязкой индивидов к их генотипам через объединительную таблицу. Таким образом, было бы легко найти все генотипы человека или всех людей, имеющих определенный генотип.
Ниже приведена уменьшенная версия этих таблиц:
Table "public.genotypes"
Column | Type | Modifiers
------------------+-----------------------------+--------------------------------------------------------
id | integer | not null default nextval('genotypes_id_seq'::regclass)
ref_variation_id | integer |
value | character varying(255) |
Indexes:
"genotypes_pkey" PRIMARY KEY, btree (id)
"index_genotypes_on_ref_variation_id" btree (ref_variation_id)
Table "public.genotypes_individuals"
Column | Type | Modifiers
---------------+---------+-----------
genotype_id | integer |
individual_id | integer |
Indexes:
"index_genotypes_individuals_on_genotype_id_and_individual_id" UNIQUE, btree (genotype_id, individual_id)
"index_genotypes_individuals_on_genotype_id" btree (genotype_id)
Table "public.individuals"
Column | Type | Modifiers
---------------+-----------------------------+----------------------------------------------------------
id | integer | not null default nextval('individuals_id_seq'::regclass)
hap_id | character varying(255) |
population_id | integer |
sex | character varying(255) |
Indexes:
"individuals_pkey" PRIMARY KEY, btree (id)
"index_individuals_on_hap_id" UNIQUE, btree (hap_id)
Узким местом сейчас является поиск всех генотипов человека и сортировка их по позициям. Это часто используется и гораздо важнее, чем поиск людей по генотипу. Примеры некоторых из этих запросов:
Простой поиск всех генотипов человека
SELECT * FROM "genotypes" INNER JOIN "genotypes_individuals" ON "genotypes" .id = "genotypes_individuals" .genotype_id WHERE ("genotypes_individuals" .individual_id = 2946)
Обычно, хотя это ограничено, потому что есть много генотипов. Нас часто интересуют только те, кто находится на определенной хромосоме.
SELECT * FROM "genotypes" INNER JOIN "genotypes_individuals" ON "genotypes" .id = "genotypes_individuals" .genotype_id WHERE ("genotypes_individuals" .individual_id = 2946) AND ("genotypes" .ref_variation_id 37, IN3, 37 (IN 37) ..))
Нам также иногда нужно идти другим путем.
ВЫБРАТЬ * ИЗ "индивидуумов" ВНУТРЕННЕЕ СОЕДИНЕНИЕ "genotypes_individuals" ВКЛ "индивидуумов" .id = "genotypes_individuals" .individual_id ГДЕ ("genotypes_individuals" .genotype_id = 53430)
Каждый раз, когда в базу данных добавляется новый человек, таблица соединений увеличивается примерно на 3 миллиона строк. Интуитивно, с точки зрения дизайна, это кажется плохим, потому что добавление новых людей замедлит производительность любого процесса, использующего существующие данные.
Я понимаю, что базы данных предназначены для эффективной обработки больших таблиц, но мы уже сталкиваемся с узкими местами из-за дискового ввода-вывода. Отдельный запрос все еще несущественен, но тысячи из них быстро складываются. Мы можем несколько облегчить эту проблему, распределив БД по нескольким дискам. Тем не менее, я хотел посмотреть, есть ли другие альтернативы там. Мне было интересно, можно ли каким-то образом отделить записи в таблице соединений по индивидуальному_идиду, что, возможно, не повлияло бы на поиск от отдельных лиц к генотипам, добавив дополнительные строки индивидуальных генотипов в таблицу соединений. Или индексы уже делают это?