简体   繁体   English

MySQL 使用 JOIN 和 COUNT 进行查询优化

[英]MySQL Query optimization with JOIN and COUNT

I have the following MySQL Query:我有以下 MySQL 查询:

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

The idea being to select a release and count how many other sites had also released it prior to the recorded date, to get the position.想法是将 select 发布并计算在记录日期之前有多少其他网站也发布了它,以获得 position。

Explain says:解释说:

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   

Any suggestions on how to eliminate the Using temporary;关于如何消除 Using 临时的任何建议; Using filesort?使用文件排序? It takes a loooong time.这需要很长时间。 The indexes I have thought of and tried haven't helped anything.我想到并尝试过的索引没有任何帮助。

This answer below maybe not change explain output, however if your major problem is sorting data, which it identified by removing order clause will makes your query run faster , try to sort your subquery join table first and your query will be:下面的这个答案可能不会改变解释 output,但是如果您的主要问题是排序数据,它通过删除 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

Note: My db version is mysql-5.0.96-x64, maybe in another version you get different result.注意:我的数据库版本是 mysql-5.0.96-x64,也许在另一个版本中你会得到不同的结果。

Try adding an index on tracers.releaseid and one on tracers.date尝试在tracers.date上添加一个索引,在tracers.releaseid上添加一个

  1. make sure you have an index on releaseid.确保你有一个关于 releaseid 的索引。
  2. flip your JOIN, the sub-query must be on the left side in the LEFT JOIN.翻转您的 JOIN,子查询必须在 LEFT JOIN 的左侧。
  3. put the ORDER BY and LIMIT clauses inside the sub-query.将 ORDER BY 和 LIMIT 子句放在子查询中。

Try having two indices, one on (date) and one on (releaseid, date) .尝试有两个索引,一个在(date)上,一个在(releaseid, date)上。

Another thing is that your query does not seem to be doing what you describe it does.另一件事是您的查询似乎没有按照您的描述进行。 Does it actually count correctly?它实际上计算正确吗?

Try rewriting it as:尝试将其重写为:

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

or as:或作为:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM