2015-06-11 108 views
0

我想比较具有超过1,000,000行的同一个表的值。以下是我的查询,需要大约25秒才能获得结果。MySQL加入性能真的很慢

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 

enter image description here

enter image description here

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

感谢。

+2

1)看来你不需要两个子查询。只需将所有表格连在一起。 2)不要使用IN(),这对MySQL来说可能很慢。改用连接。 3)不要在子查询中使用*。 – Tim3880

+0

感谢您的评论,我已经使用所有表格的加入,但它会让情况变得更糟糕。如果我通过电子邮件向您发送邮件,您是否可以使用此表格进行游戏? –

+0

你的'选择'是荒谬的。您正在选择六列,但根据'on'子句,只有三个值。 –

回答

0

首先,你有一个愚蠢的查询。您正在检索六列,但只有三个值。看看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)指标。

+0

感谢您的评论,我试图做的实际上是从“t”表中检索内部版本号1031719的所有值,并检索另一个内部版本号1030716的所有值,然后比较两个值之间的值。因为所有值都基于不同的内部版本号而不同。 –

+0

SELECT 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.IN​​TERNAL_FORCE,b.MPC_FORCE,b.SPC_FORCE,b.TRANSLATION,b.VELOCITY,b。load_number 这是完整的选择部分.. –

0

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

问题#2:

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

优化,因为无论子查询甚少。你可以把两个子查询合并为一个,就像Gordon试图做的那样?如果不是,则将其中一个放入TEMPORARY TABLE中,并为该表添加适当的索引,以便ON能够使用它。可能PRIMARY KEY(studyid, load_number, number)

脚注:MySQL的最新版本已经通过动态生成指数由上这些问题的改进。你使用什么版本?

+0

谢谢你的评论。我想知道,一旦我创建一个临时表,那么我是否需要加入临时表的表?或如何使用Select语句应用临时表?你能向我解释一下吗? –

+0

'CREATE TEMPORARY TABLE xx(PRIMARY KEY ...)SELECT ...';然后...'SELECT ... FROM(SELECT ..另一个子查询...)JOIN xx on .. 3 fields ..等等' –