缓慢查询有很多连接和' IN'声明

时间:2015-04-25 08:09:26

标签: mysql sql

我的查询速度很慢,我相信这是由于' IN'声明。 ' IN'中的ID列表声明可能非常大,如250+。此查询每次都会运行2秒以上,这太慢了。

有没有办法加快速度?

SELECT u.achternaam as achternaam, u.code as code, srt.niveaus as niveaus, srt.soortid AS soortid,IFNULL( scr.gehaald,'0')AS gehaald, IFNULL( scr.gespeeld,'0')AS gespeeld, IF( srt.niveaus =1,'n.v.t.', IFNULL(scr.huidigniveau,'0') )AS niveautext 
FROM gebruikers u 
LEFT JOIN ( SELECT scoreid,schoolcode, soortid, userid, gehaald, gespeeld, huidigniveau 
            FROM scores) scr
ON scr.userid = u.code              
LEFT JOIN ( SELECT soortid,niveaus,spelid,titel,verberg 
            FROM soorten 
            WHERE soortid IN (13,14,15,16,17,561,566,567,568,574,575,1,100,101,102,103,104,105,107,108,109,11,110,112,113,114,115,116,117,118,12,120,121,122,123,124,125,126,127,128,129,130,131,133,134,137,138,140,141,144,145)) srt
ON scr.soortid = srt.soortid
LEFT JOIN(SELECT spelnaam,spelid,vakid FROM spellen) g
ON srt.spelid=g.spelid
LEFT JOIN(SELECT vakid,vaknaam FROM vakken) vak
ON g.vakid=vak.vakid
WHERE u.groepsid='28' AND u.schoolcode ='1'  AND srt.verberg =0
ORDER BY achternaam,vak.vaknaam,g.spelnaam,srt.titel ASC

解释选择的结果

explain

2 个答案:

答案 0 :(得分:2)

不要使用子查询,只需直接加入表。

请注意,srt.verberg = 0测试应该在ON子句中,而不是WHERE子句中。当您使用LEFT JOIN时,第二个表格中的所有条件都应该在ON中,除非您正在测试因未找到匹配而导致的NULL

SELECT u.achternaam as achternaam, u.code as code, srt.niveaus as niveaus, srt.soortid AS soortid,IFNULL( scr.gehaald,'0')AS gehaald, IFNULL( scr.gespeeld,'0')AS gespeeld, IF( srt.niveaus =1,'n.v.t.', IFNULL(scr.huidigniveau,'0') )AS niveautext 
FROM gebruikers u 
LEFT JOIN scores scr
ON scr.userid = u.code              
LEFT JOIN soorten srt
ON scr.soortid = srt.soortid
    AND srt.soortid IN (13,14,15,16,17,561,566,567,568,574,575,1,100,101,102,103,104,105,107,108,109,11,110,112,113,114,115,116,117,118,12,120,121,122,123,124,125,126,127,128,129,130,131,133,134,137,138,140,141,144,145)
    AND srt.verberg = 0
LEFT JOIN spellen g
ON srt.spelid=g.spelid
LEFT JOIN vakken vak
ON g.vakid=vak.vakid
WHERE u.groepsid='28' AND u.schoolcode ='1'
ORDER BY achternaam, vak.vaknaam, g.spelnaam, srt.titel ASC

此外,请确保您确实需要使用LEFT JOIN而不是INNER JOIN。仅当您希望结果包含第一个表中第二个表中没有匹配项的行时,才应使用LEFT JOININNER JOIN性能通常更好,因此您应该在适当的时候使用它。

答案 1 :(得分:1)

您正在加入子查询结果,我希望执行计划程序在提高效率方面遇到问题。只需加入表格:

select
  u.achternaam as achternaam,
  u.code as code,
  srt.niveaus as niveaus,
  srt.soortid as soortid,
  ifnull(scr.gehaald,'0') as gehaald,
  ifnull(scr.gespeeld,'0') as gespeeld,
  if(srt.niveaus = 1, 'n.v.t.', ifnull(scr.huidigniveau,'0')) as niveautext 
from
  gebruikers u 
  left join scores scr on scr.userid = u.code
  left join soorten srt on srt.soortid IN (13,14,15,16,17,561,566,567,568,574,575,1,100,101,102,103,104,105,107,108,109,11,110,112,113,114,115,116,117,118,12,120,121,122,123,124,125,126,127,128,129,130,131,133,134,137,138,140,141,144,145)) and scr.soortid = srt.soortid and srt.verberg = 0
  left join spellen g on srt.spelid = g.spelid
  left join vakken vak on g.vakid = vak.vakid
where
  u.groepsid = '28' and u.schoolcode = '1'
order by
  achternaam,
  vak.vaknaam,
  g.spelnaam,
  srt.titel asc

注意:我将条件srt.verberg = 0移动到了联接中,将其放在where中使其像内部联接一样工作。