SQL初学者 - 为什么我的MySQL Join-query不使用索引/工作这么慢?

时间:2013-01-29 12:30:57

标签: sql join indexing

我的MySQL 5.5数据库出现了以下问题 - 我对此很新,所以它可能非常明显,但是我似乎无法得到它:

两张桌子:


表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; 的所有信息

我尝试了以下声明:

{{1}}

这里是该查询的解释:

http://i.stack.imgur.com/QV3ER.jpg(点击放大)

现在这个查询非常非常慢(我实际上从未完成它,在大约10分钟之后stopepd)并且我可以想象它是因为没有用于第二个表的索引,尽管两个ID都是主键,因此它们应该是索引对吗?

如果单独执行,内部选择的结果需要~3 sek并返回~3k行。所以我认为问题是制作3000 * 15mio比较因为表2中检查了每一行。

但我该如何解决这个问题?

任何帮助表示赞赏 -voiD

4 个答案:

答案 0 :(得分:4)

这可能是因为你加入了子查询。尝试:

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

答案 1 :(得分:1)

与其他解决方案略有不同。考虑您首先尝试获得的主要标准......给定全局肽值的那些肽元素。确保您在此表上有关于您可能要查询的任何此类条件的索引(您有)。但是,如果您发现将针对同一个表查询多个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之后),将不会像预期的那样受益。

答案 2 :(得分:0)

tipp将避免子选择。有时它们很棒,但通常会导致性能不佳。更好的方法可能是:

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上没有索引。加一个,你可能会没事的。

答案 3 :(得分:0)

  

我认为问题可能是因为你现在正在创建一个交叉连接   而不是内部联接。你的子查询正在创建一个笛卡儿   产品1500万行* 300万行。

     

使用内部联接,你将这个数字减少到1500万* 3000   行。

     

它仍然是一个巨大的数字。在Sql端,您可以通过发出来限制它   前10名或前20名。

     

在前端,如果它是C#你应该使用分页技术   gridviewpager或数据源上的其他分页技术假设你   将在前端显示结果,该结果将位于顶部   您的SQL加入查询和第20页结果一次。