优化MySQL查询

时间:2013-05-30 16:30:07

标签: mysql query-optimization

我有一个包含3个表的MySQL数据库

Keywords
id, keyword, projects_id

Year
results_id*, jan, feb, mar, ..., nov, dec

Results
id, keywords_id*, country, user

star = foreign key

我需要找到项目1中存在的任何关键字生成的年度总量,并且还存在于按国家和用户分组的项目2,3和4中。

这是我到目前为止所拥有的

SELECT SUM(y.january + 
           y.february +
           ...
           y.december) AS 'sum',
       r.country , r.user
       FROM results r, year y           
       WHERE y.results_id = r.id 
             AND keywords_id IN(
                                   SELECT DISTINCT k.id
                                   FROM keywords k 
                                   JOIN keywords kk ON k.keyword = kk.keyword
                                   WHERE k.projects_id = 1 
                                   AND kk.projects_id IN (2,3,4)
                                   )
       GROUP BY country, user;

我的逻辑是:

  1. 使用JOIN查找属于项目1的所有关键字的ID,这些关键字也在项目2,3,4中。
  2. 然后使用包含任何关键字ID的keywords_id条目查找任何结果
  3. 最后从年份表和国家/地区用户
  4. 一起添加所有卷

    我尝试了第一步的子查询(括号内的子查询),它返回了超过1700个关键字

    但是当我在30分钟后尝试整个关键字时,我没有得到任何结果。

    如何重写查询以加快速度,或者如果我做错了什么呢?

    提前多多感谢

1 个答案:

答案 0 :(得分:1)

以下是我写它的方式。第一个查询通过项目1关键字的限定符获取所有4个项目1,2,3和4中的所有关键字,并将2,3和4加入到其他项目中。如果您想要项目1的最小值和2的任意值, 3或4,我会略微改变它。

从那时起,只有加入到结果和年表。现在,帮助优化。您的关键字表应该有一个索引(id,projects_id)。结果表应该有一个索引(keywords_id,country,user) - 要在组中帮助的国家和用户。

select STRAIGHT_JOIN
      r.country,
      r.user,
      SUM( y.january + y.february + y.march
         + y.april   + y.may      + y.june
         + y.july    + y.august   + y.september
         + y.october + y.november + y.december ) as AllMonths
   from 
      ( SELECT k.id
           FROM keywords k
              JOIN keywords k2 on k.id = k2.id AND k2.project_id = 2
              JOIN keywords k3 on k.id = k3.id AND k3.project_id = 3
              JOIN keywords k4 on k.id = k4.id AND k4.project_id = 4
           where 
              k.project_id = 1 ) KeywordsInAll             
         JOIN results r
            ON KeywordsInAll.ID = r.keywords_id
            JOIN `year` y
               ON r.id = y.results_id
   group by 
      r.country,
      r.user

我将内部查询更改为START,关键字至少来自项目1 ...如果项目1只有15个关键字(夸大,但是示例),则查询10,000个关键字没有意义

根据您发布的评论,我只是将预先查询更改为几乎与您的相同,但保持在第一位并保留“STRAIGHT_JOIN”

      ( SELECT DISTINCT k.id
           FROM keywords k
              JOIN keywords k2 on k.id = k2.id 
               AND k2.project_id IN (2, 3, 4 )
           where 
              k.project_id = 1 ) KeywordsInAll