【问题标题】:MySQL Query optimization with JOIN and COUNT使用 JOIN 和 COUNT 优化 MySQL 查询
【发布时间】:2013-11-04 07:40:00
【问题描述】:

我有以下 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

这个想法是选择一个版本并计算在记录日期之前有多少其他网站也发布了它,以获得职位。

解释说:

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   

关于如何消除 Using 临时的任何建议;使用文件排序?这需要很长时间。我想过并尝试过的索引没有任何帮助。

【问题讨论】:

  • 您的确切指数是多少? (releaseid)(releaseid, date)(date, pos)?

标签: mysql file sorting


【解决方案1】:

尝试在tracers.releaseid 上添加一个索引,在tracers.date 上添加一个索引

【讨论】:

    【解决方案2】:
    1. 确保您在 releaseid 上有一个索引。
    2. 翻转你的JOIN,子查询必须在LEFT JOIN的左边。
    3. 将 ORDER BY 和 LIMIT 子句放在子查询中。

    【讨论】:

      【解决方案3】:

      尝试使用两个索引,一个在(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
      

      【讨论】:

        【解决方案4】:

        下面的这个答案可能不会改变解释输出,但是如果您的主要问题是排序数据,它由 删除 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
        

        注意:我的数据库版本是mysql-5.0.96-x64,可能在另一个版本中你会得到不同的结果。

        【讨论】:

          猜你喜欢
          • 2012-01-28
          • 1970-01-01
          • 2011-02-14
          • 1970-01-01
          • 1970-01-01
          • 2012-10-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多