2011-07-17 74 views
0

我有以下MySQL查询:MySQL查询优化与JOIN和COUNT

SELECT t1.id, t1.releaseid, t1.site, t1.date, t2.pos FROM `tracers` as t1 
LEFT JOIN (
    SELECT `releaseid`, `date`, COUNT(*) AS `pos` 
    FROM `tracers` GROUP BY `releaseid` 
) AS t2 ON t1.releaseid = t2.releaseid AND t2.date <= t1.date 
ORDER BY `date` DESC , `pos` DESC LIMIT 0 , 100 

的想法是选择一个版本,并指望有多少其他网站也发布了它之前的录制日期,以获得位置。

解释说:

id select_type table type possible_keys key key_len ref rows Extra 
1 PRIMARY t1 ALL NULL NULL NULL NULL 498422 Using temporary; Using filesort 
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 91661  
2 DERIVED tracers index NULL releaseid 4 NULL 498422 

如何消除使用临时任何建议;使用filesort?这需要很长的时间。我想到并尝试过的索引没有任何帮助。

+0

你的确切指数是什么? '(releaseid)','(releaseid,date)'和'(date,pos)'? – knittl

回答

0

尝试tracers.date

0
  1. 上添加tracers.releaseid和一个索引确保您有releaseid的索引。
  2. 翻转您的JOIN,子查询必须位于左侧的LEFT JOIN中。
  3. 将ORDER BY和LIMIT子句放入子查询中。
0

尝试使用两个索引,一个在(date)上,另一个在(releaseid, date)上。

另一件事是你的查询似乎没有做你描述它的事情。它实际计数是否正确?

尝试重写它:

SELECT t1.id, t1.releaseid, t1.site, t1.`date` 
    , COUNT(*) AS pos 
FROM tracers AS t1 
    JOIN tracers AS t2 
    ON t2.releaseid = t1.releaseid 
    AND t2.`date` <= t1.`date` 
GROUP BY t1.releaseid 
ORDER BY t1.`date` DESC 
     , pos DESC 
LIMIT 0 , 100 

或为:

SELECT t1.id, t1.releaseid, t1.site, t1.`date` 
    , (SELECT COUNT(*) 
     FROM tracers AS t2 
     WHERE t2.releaseid = t1.releaseid 
      AND t2.`date` <= t1.`date` 
     ) AS pos 
FROM tracers AS t1 
ORDER BY t1.`date` DESC 
     , pos DESC 
LIMIT 0 , 100 
0

这个答案下面也许不会改变解释输出,但如果您的主要问题是由对数据进行排序,其中确定删除order子句将使您的查询运行更快,请尝试首先对您的子查询连接表进行排序,您的查询将为:

SELECT t1.id, t1.releaseid, t1.site, t1.date, t2.pos FROM `tracers` as t1 
LEFT JOIN (
    SELECT `releaseid`, `date`, COUNT(*) AS `pos` 
    FROM `tracers` GROUP BY `releaseid` 
    ORDER BY `pos` DESC -- additional order 
) AS t2 ON t1.releaseid = t2.releaseid AND t2.date <= t1.date 
ORDER BY `date` DESC , `pos` DESC LIMIT 0 , 100 

注意:我的db版本是mysql-5.0.96-x64,也许在另一个版本中会得到不同的结果。