[英]SQL beginner - Why does my MySQL Join-query use no index / work so slow?
我的MySQL 5.5 DB遇到以下問題-我對此很陌生,因此可能很明顯出了什么問題,但我似乎無法理解:
兩張桌子:
表格1
CREATE TABLE `sequence_matches` (
`Sample_ID` INT(6) NOT NULL,
`Sequence_Match_ID` INT(8) NOT NULL,
`Start` INT(6) NULL DEFAULT NULL,
`End` INT(6) NULL DEFAULT NULL,
`Coverage` DOUBLE(5,2) NULL DEFAULT NULL,
`Frag_String` VARCHAR(255) NULL DEFAULT NULL,
`rms_mass_error_prod` DOUBLE(10,4) NULL DEFAULT NULL,
`rms_rt_error_prod` DOUBLE(10,4) NULL DEFAULT NULL,
PRIMARY KEY (`Sample_ID`, `Sequence_Match_ID`)
)
和
表2
CREATE TABLE `peptide_identifications` (
`Sample_ID` INT(6) NOT NULL,
`Peptide_identification_ID` INT(8) NOT NULL,
`Mass_error` DOUBLE(10,4) NULL DEFAULT NULL,
`Mass_error_ppm` DOUBLE(10,4) NULL DEFAULT NULL,
`Score` DOUBLE(10,4) NULL DEFAULT NULL,
`Type` VARCHAR(45) NULL DEFAULT NULL,
`global_pept_ID` INT(8) NOT NULL,
PRIMARY KEY (`Sample_ID`, `Peptide_identification_ID`),
INDEX `Index` (`global_pept_ID`)
)
它們每個包含約1500萬行。
現在,我希望從Table2
中的所有這些行(其中global_pept_id = 27443
,然后使用這些行的peptide_identification_id
,來查詢來自Table1
所有信息,其中peptide_identification_id = sequence_match_id
。
我嘗試了以下語句:
SELECT * from sequence_matches
JOIN (
SELECT peptide_identification_id
FROM peptide_identifications
WHERE global_pept_id = 27443
) as tmp_pept
ON sequence_match_id = peptide_identification_id;
這是該查詢的解釋:
現在這個查詢非常非常慢(我實際上從未完成過查詢,大約10分鍾后就停止了查詢),我可以想象這是因為盡管兩個ID都是主鍵,但第二個表沒有使用索引,因此應該對它們進行索引嗎?
內部選擇的結果需要大約3 sek,如果單獨執行,則返回大約3k行。 所以我認為問題是使3000 * 15mio比較導致表2中檢查了每一行。
但是我該如何解決呢?
任何幫助表示贊賞-voiD
可能是因為您要加入子查詢。 嘗試:
SELECT sm.*, pi.peptide_identification_id
FROM sequence_matches sm
INNER JOIN peptide_identifications pi
ON sm.id = pi.peptide_identification_id
WHERE pi.global_pept_id = 27443
與其他解決方案略有不同。 考慮您要首先獲得的主要標准...給定全局肽值的那些肽元素。 確保您在該表上有一個可能要查詢的條件(根據您有)在該索引上。 但是,如果發現要針對同一張表查詢多個WHERE條件,請嘗試准備/擁有一個對兩個條件都有用的索引。
然后,將JOIN條件放在PK / FK關系的另一個表上以獲取那些記錄。
SELECT *
from
peptide_identification PI
JOIN sequence_matches SM
ON PI.peptide_identification_id = SM.sequence_match_id
WHERE
PI.global_pept_id = 27443
沒有適當的索引會嚴重破壞查詢的性能。 您的Sequence_Matches表應該在(Sequence_match_ID)上有一個索引,以幫助其優化。 將其放在第二個位置(在sample_id之后)將不會像預期的那樣受益。
一個小技巧是避免子選擇。 有時它們很棒,但通常會導致性能不佳。 更好的方法可能是:
SELECT * from peptide_identification as tmp_pept
JOIN sequence_matches
ON sequence_matches.sequence_match_id = tmp_pept.peptide_identification_id
WHERE tmp_pept.global_pept_id = 27443
這有招嗎?
編輯:不,真正的問題是sequence_match_id上沒有索引。 加一個,您可能會好起來的。
我認為問題可能是因為您現在創建的是交叉聯接而不是內部聯接。 您的子查詢創建的笛卡爾積為1500萬行* 300萬行。
使用內部聯接,您可以將數目減少到1500萬* 3000行。
它仍然是一個巨大的數字。 在Sql端,您可以通過發出TOP 10或TOP 20來限制它。
在前端,如果是C#,則應在數據源上使用諸如gridviewpager的分頁技術或其他分頁技術,假設u將在前端顯示結果,該結果將位於SQL Join查詢的頂部,第20頁的結果位於一個時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.