簡體   English   中英

SQL初學者-為什么我的MySQL Join查詢不使用索引/工作這么慢?

[英]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; 

這是該查詢的解釋:

http://i.stack.imgur.com/QV3ER.jpg (點擊放大)

現在這個查詢非常非常慢(我實際上從未完成過查詢,大約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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM