[英]Large Join Tables and Scaling
我們有一個快速增長的數據庫,其中包含幾個大型聯接表(當前為數十億行),但是隨着這些表的增長,查詢時間也受到了影響。 令人擔心的是,隨着更多數據添加到這些聯接表鏈接的表中,聯接表將繼續以更快的速度增長,並對查詢速度產生不利影響。
我正在處理一個存儲基因組信息的數據庫。 與存在DNA變異的基因座相對應的許多標記(約300萬個)與已在這些基因座確定其基因型的個體相關。 每個標記都有許多可能的基因型,每個個體都必須具有一個。
當數據庫(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,143) )
我們還偶爾需要走另一條路。
SELECT * FROM“ individuals” INNER JOIN“ genotypes_individuals” ON“ individuals” .id =“ genotypes_individuals” .individual_id WHERE(“ genotypes_individuals” .genotype_id = 53430)
每次將新的個人添加到數據庫中時,聯接表都會增加大約300萬行。 從設計的角度來看,這似乎很糟糕,因為添加新的人員會降低使用現有數據的任何流程的性能。
我知道數據庫是為有效處理大型表而設計的,但是由於驅動器IO,我們已經遇到瓶頸。 單個查詢仍然無關緊要,但其中的數千個會迅速增加。 通過將db分布在多個驅動器上,我們可以在某種程度上緩解此問題。 但是,我想看看是否還有其他選擇。 我一直在想是否可以通過personal_id分隔聯接表條目,這可能會通過向聯接表添加其他個體基因型行而不會影響從個體到基因型的查找。 還是索引已經做到了?
您是否看過表分區 ?
我會考慮測試使用自然鍵而不是ID號的模式。
您查找的所有個體基因型
SELECT *
FROM "genotypes"
INNER JOIN "genotypes_individuals"
ON "genotypes".id = "genotypes_individuals".genotype_id
WHERE ("genotypes_individuals".individual_id = 2946 )
變成
SELECT *
FROM genotypes_individuals
WHERE (individual_id = 2946)
有時那會更快。 有時候不是。
在我們的生產系統上切換到自然鍵后,性能中值提高了10倍。使用自然鍵,某些查詢的運行速度提高了100倍,因為自然鍵消除了很多聯接。 有些查詢的運行速度也較慢。 但是無論如何,中間速度的提升令人印象深刻。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.