【问题标题】:MySQL Join performance is really slowMySQL Join 性能真的很慢
【发布时间】:2015-08-26 11:46:27
【问题描述】:

我正在尝试将值与具有超过 1,000,000 行的同一个表进行比较。以下是我的查询,大约需要 25 秒才能得到结果。

EXPLAIN SELECT DISTINCT a.studyid,a.number,a.load_number,b.studyid,b.number,b.load_number FROM
(SELECT t1.*, buildnumber,platformid FROM t t1
INNER JOIN testlog t2 ON t1.`testid` = t2.`testid`
WHERE (buildnumber =1031719 AND platformid IN (SELECT platformid FROM platform WHERE platform.`Description` = "Windows 7 SP1"))
)AS a
JOIN
(SELECT t1.*,buildnumber,platformid FROM t t1
INNER JOIN testlog t2 ON t1.`testid` = t2.`testid`
WHERE (buildnumber =1030716 AND platformid IN (SELECT platformid FROM platform WHERE platform.`Description` = "Windows 7 SP1"))
)AS b
ON a.studyid=b.studyid AND a.load_number = b.load_number AND a.number = b.number

谁能帮我改进这个查询以获得足够快的结果? 这里的问题是即使我有 number 和 load_number 索引,查询也不使用它。我不知道为什么它总是被忽略..

谢谢。

【问题讨论】:

  • 1) 看来您不需要两个子查询。只需将所有表连接在一起。 2) 不要使用 IN () ,这对 MySQL 来说会很慢。改用加入。 3) 不要在子查询中使用 *。
  • 感谢您的评论,我已经为所有表格使用了联接,但它变得更糟了..如果我通过电子邮件发送给您,您可以玩这个表格吗?
  • 你的select 太荒谬了。您正在选择六列,但只有三个值,基于 on 子句。
  • 你可以先试试答案。如果问题仍然存在,请告诉我们。
  • 是的,问题仍然存在..我想不通..

标签: mysql performance join


【解决方案1】:

首先,您有一个愚蠢的查询。您正在检索六列,但只有三个值。查看on 子句。

我认为最好的办法是使用条件聚合重写查询。我认为以下是等价的:

SELECT t1.studyid, t1.load_number, t1.number
FROM t t1 INNER JOIN
     testlog t2
     ON t1.testid = t2.testid
WHERE t2.buildnumber IN (1031719, 1030716) AND
      platformid IN (SELECT platformid FROM platform p WHERE p.Description = 'Windows 7 SP1'))
GROUP BY studyid, load_number, number
HAVING MIN(buildnumber) <> MAX(buildnumber)

对于此查询,您需要在 platform(Description, platformid)testlog(buildnumber, platformid)t(testid) 上建立索引。

【讨论】:

  • 感谢您的评论,我实际上正在尝试从“t”表中检索内部版本号 1031719 的所有值,并检索另一个内部版本号 1030716 的所有值,然后在值之间进行比较。因为根据不同的内部版本号,所有值都是不同的。
  • 选择 a.studyid,a.number,a.ACCELERATION,a.APPLIED_FORCE,a.INTERNAL_FORCE,a.MPC_FORCE,a.SPC_FORCE,a.TRANSLATION,a.VELOCITY,a.load_number,b .studyid,b.number,b.ACCELERATION,b.APPLIED_FORCE,b.INTERNAL_FORCE,b.MPC_FORCE,b.SPC_FORCE,b.TRANSLATION,b.VELOCITY,b.load_number 这是完整的选择部分..
【解决方案2】:

问题 #1:
IN ( SELECT ... ) 优化非常很差。子查询一次又一次地重新运行。看起来您期望从该查询中获得一个 id;如果是这样,请将其更改为= ( SELECT ... )。这样它将只运行一次。

问题 #2:

FROM ( SELECT ... )
JOIN ( SELECT ... ) ON ...

优化不佳,因为没有子查询。您能像 Gordon 尝试的那样将两个子查询合并为一个吗?如果没有,则将其中一个放入TEMPORARY TABLE 并为该表添加适当的索引,以便ON 能够使用它。应该是PRIMARY KEY(studyid, load_number, number)

脚注:最新版本的 MySQL 通过动态生成索引对这些问题进行了改进。你用的是什么版本?

【讨论】:

  • 感谢您的评论。我想知道一旦我创建了一个临时表,那么我是否需要将一个表与临时表连接起来?或者如何使用 Select 语句应用临时表?你能多解释一下吗?
  • CREATE TEMPORARY TABLE xx (PRIMARY KEY...) SELECT ...;那么……SELECT ... FROM ( SELECT ..the other subquery...) JOIN xx on .. 3 fields.. Etc;
猜你喜欢
  • 1970-01-01
  • 2017-02-27
  • 1970-01-01
  • 2021-10-28
  • 2014-03-15
  • 1970-01-01
  • 2012-06-26
  • 2018-09-07
  • 1970-01-01
相关资源
最近更新 更多