1

我的 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 万行。

现在,我想要来自Table2where的所有这些行global_pept_id = 27443,然后使用其中peptide_identification_id的那些,从Table1where查询所有信息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

4

4 回答 4

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
于 2013-01-29T12:36:36.427 回答
1

与其他解决方案略有不同。首先考虑您尝试获得的主要标准……给定全局肽值的那些肽元素。确保您在此表上具有您可能要查询的任何此类条件的索引(您有)。但是,如果您发现您将针对同一个表查询多个 WHERE 条件,请尝试准备/拥有一个有助于满足这两个条件的索引。

然后,在 PK/FK 关系上对另一个表添加 JOIN 条件以获取这些记录。

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 之后)不会像预期的那样受益。

于 2013-01-29T12:49:53.293 回答
0

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

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

于 2013-01-29T12:36:05.080 回答
0

我认为问题可能是因为您现在创建了交叉连接而不是内部连接。您的子查询正在创建 1500 万行 * 300 万行的笛卡尔积。

使用内部连接,您可以将该数字减少到 1500 万 * 3000 行。

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

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

于 2013-01-29T12:39:27.460 回答