2013-05-27 117 views
0

以下是我的聚合查询需要1.1秒。该查询有多个连接。列将优化查询的索引。优化聚合查询

  EXPLAIN SELECT straight_join 
      aggsm.tdm_id AS topid,    
      sum(aggsm.m_count) AS mencnt , 
      sum(aggsm.ps_count) AS pscnt, 
      sum(aggsm.ns_count) AS ngscnt, 
      topdm.topic_name AS topname 
     FROM AGG_MENTION AS aggsm 
     JOIN TOPICDM AS topdm ON aggsm.topicdm_id = topdm.topicdm_id 
     JOIN LOCATIONDM AS locdm ON aggsm.locationdm_id = locdm.locationdm_id 
     JOIN CITY AS citydm ON locdm.city_id = citydm.city_id 
     JOIN STATE AS statedm ON citydm.state_id = statedm.state_id 
     WHERE aggsm.cdm_id = 11 
     AND aggsm.ei_type IN (1,2,3,4) 
     AND aggsm.datedm_id BETWEEN 20130101 AND 20130522 
     AND statedm.country_id IN (1,2,3,4) 
     AND topdm.topic_group_id IN (1,2,3,4,5,6,7)  
     GROUP BY aggsm.topicdm_id 
     -- ORDER BY aggsm.topicdm_id DESC,sum(aggsm.m_count) DESC 
     LIMIT 0,200000 

以下是解释输出:

1 SIMPLE aggsm ref PRIMARY,datedm_id_UNIQUE,agg_sm_locdm_fk_idx,agg_sm_comdm_fk_idx,agg_sm_topdm_fk_idx,agg_sm_datedm_fk_idx,agg_em_indtype_fk_idx,comp_top_dt,l_idx comp_top_dt 8 const 202129 Using where; Using index 
    1 SIMPLE topdm eq_ref PRIMARY,topicdm_id_UNIQUE,topdm_grp_id_idx,id_idx PRIMARY 8 opinionleaders.aggsm.topicdm_id 1 Using where 
    1 SIMPLE locdm eq_ref PRIMARY,city_id_UNIQUE,locationdm_id_UNIQUE,loc_city_fk_idx,id_idx PRIMARY 8 opinionleaders.aggsm.locationdm_id 1 
    1 SIMPLE citydm eq_ref PRIMARY,city_id_UNIQUE,city_state_fk_idx,id_idx PRIMARY 8 opinionleaders.locdm.city_id 1 
    1 SIMPLE statedm eq_ref PRIMARY,state_id_UNIQUE,state_country_fk_idx,id_idx PRIMARY 8 opinionleaders.citydm.state_id 1 Using where 

by子句在取消订单将导致aggsm表使用“使用临时使用文件排序”

我们如何优化查询或定义index

+0

一些想法......不知道这使它更好 - 只是想帮助虽然:) 1)如果可能分裂这个庞大的查询(例如与PHP)到较小的部分。 2)尽量减小结果以保留内存;主题名称可能会使它相当大或考虑分页的结果3)检查你的MySQL配置,并提高取决于你使用的引擎的限制 – viljun

+0

1.1对我来说似乎相当好:-(。然而,你有一个跨越(cdm_id ,ei_type,datedm_id)? – Strawberry

回答

0

1)LIMIT 0,200000绝对不是一个好的解决方案,我几乎看不到一个应用程序,你需要如此大量的数据,将它分成块

2)在ORDER BY子句中,您要指定和sum(aggsm.m_count) - 这是一个聚合函数,尝试解决它作为mencnt(因此ORDER BY aggsm.topicdm_id DESC,mencnt DESC),不知道SQL服务器可以根据需要理解它

0

轻微重新格式化查询以提高可读性并查看关系和相关列以便进行索引考虑。由于您的Aggsm表正在按topicdm_id分组,因此我至少会尝试使用此列和列获得覆盖索引,以便到达您的连接表,因此无需转到原始页数据,直到它具有合格的记录跟...共事。另外,为你的where子句包含组件。我建议对表的索引有

table  index 
agg_mention (cdm_id, ei_type, datedm_id, topicdm_id, locationdm_id) 
topicdm  (topicdm_id, topic_group_id) 
state  (state_id, country_id) 
locationdm (locationdm_id) 
city   (city_id) 

SELECT straight_join 
     aggsm.tdm_id AS topid, 
     sum(aggsm.m_count) AS mencnt, 
     sum(aggsm.ps_count) AS pscnt, 
     sum(aggsm.ns_count) AS ngscnt, 
     topdm.topic_name AS topname 
    FROM 
     AGG_MENTION AS aggsm 
     JOIN TOPICDM AS topdm 
      ON aggsm.topicdm_id = topdm.topicdm_id 
      AND topdm.topic_group_id IN (1,2,3,4,5,6,7)  
     JOIN LOCATIONDM AS locdm 
      ON aggsm.locationdm_id = locdm.locationdm_id 
      JOIN CITY AS citydm 
       ON locdm.city_id = citydm.city_id 
       JOIN STATE AS statedm 
        ON citydm.state_id = statedm.state_id 
        AND statedm.country_id IN (1,2,3,4) 
    WHERE 
      aggsm.cdm_id = 11 
     AND aggsm.ei_type IN (1,2,3,4) 
     AND aggsm.datedm_id BETWEEN 20130101 AND 20130522 
    GROUP BY 
     aggsm.topicdm_id 
    ORDER BY 
     aggsm.topicdm_id DESC, 
     sum(aggsm.m_count) DESC 
    LIMIT 
     0,200000