繁体   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