【问题标题】:Mysql inner join with whereMysql内部连接与where
【发布时间】:2017-06-24 15:27:48
【问题描述】:
    SELECT pm.team,
       pm.username,
       count(DISTINCT if(offer_pm.revenue>0.0,adv.adv_name,NULL)) AS adv_count,
       sum(offer_pm.click),
       sum(offer_pm.install),
       sum(offer_pm.revenue),
       sum(offer_pm.cost)
FROM (pm pm
      INNER JOIN offer_pm_adv_day offer_pm ON offer_pm.pm_id=pm.id)
INNER JOIN advertiser adv ON offer_pm.adv_id=adv.id
WHERE offer_pm.logdate>='2016-01-01'
    AND offer_pm.logdate<='2017-01-01'
GROUP BY pm.team,
         pm.username

如果有where条件offer_pm.logdate&gt;='2016-01-01' and offer_pm.logdate&lt;='2017-01-01' 下面是 sql 的解释。而且成本时间长(20s)

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: offer_pm
         type: range
possible_keys: PRIMARY,adv_id_index,logdate_index
          key: PRIMARY
      key_len: 3
          ref: NULL
         rows: 713003
        Extra: Using where; Using temporary; Using filesort    -->Useing where 
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: pm
         type: eq_ref
possible_keys: PRIMARY,uniq_name_team
          key: PRIMARY
      key_len: 4
          ref: summary_report_refactor2.offer_pm.pm_id
         rows: 1
        Extra: Using where    

*************************** 3. row ***************************
           id: 1
  select_type: SIMPLE
        table: adv
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: summary_report_refactor2.offer_pm.adv_id
         rows: 1
        Extra: Using where

但是sql

SELECT pm.team,
       pm.username,
       count(DISTINCT if(offer_pm.revenue>0.0,adv.adv_name,NULL)) AS adv_count,
       sum(offer_pm.click),
       sum(offer_pm.install),
       sum(offer_pm.revenue),
       sum(offer_pm.cost)
FROM (pm pm
      INNER JOIN offer_pm_adv_day offer_pm ON offer_pm.pm_id=pm.id)
INNER JOIN advertiser adv ON offer_pm.adv_id=adv.id
GROUP BY pm.team,
         pm.username

which 不具备 where 条件。

花费时间为 2s 。解释是

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: pm
         type: index
possible_keys: PRIMARY,uniq_name_team
          key: uniq_name_team
      key_len: 604
          ref: NULL
         rows: 91
        Extra: Using index; Using filesort
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: offer_pm
         type: ref
possible_keys: adv_id_index,pm_id_index
          key: pm_id_index
      key_len: 4
          ref: summary_report_refactor2.pm.id
         rows: 10042
        Extra: Using index condition
*************************** 3. row ***************************
           id: 1
  select_type: SIMPLE
        table: adv
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: summary_report_refactor2.offer_pm.adv_id
         rows: 1
        Extra: Using where

顺便说一句,logdate 列上有一个索引。

【问题讨论】:

  • 你有什么问题?
  • logdate 列是什么类型的属性?
  • 请为表格提供SHOW CREATE TABLE
  • 您真的要包含两个 1 月 1 日的日期吗?
  • 这可能是JOIN + GROUP BY 的经典“explode-implode”问题。请注意,对于COUNT,您必须执行DISTINCT 以避免它。 SUMs 是不是太大了?是映射1:many;如果有,是哪条路?

标签: mysql optimization explain


【解决方案1】:

如果您在日志日期上有索引,请尝试以下查询:

SELECT straight_join pm.team,
       pm.username,
       count(DISTINCT if(offer_pm.revenue>0.0,adv.adv_name,NULL)) AS adv_count,
       sum(offer_pm.click),
       sum(offer_pm.install),
       sum(offer_pm.revenue),
       sum(offer_pm.cost)
FROM offer_pm_adv_day offer_pm
INNER JOIN pm ON offer_pm.pm_id=pm.id
INNER JOIN advertiser adv ON offer_pm.adv_id=adv.id
WHERE offer_pm.logdate>='2016-01-01'
    AND offer_pm.logdate<='2017-01-01'
GROUP BY pm.team,
         pm.username ;

这基本上与您的表格的组织方式有关。 以及执行计划者使用什么键。

通过使用straight_join,您可以强制以某种方式加入表,有时可以稍微缩短执行时间。 也可以看看mysql的force key或者force index选项。

或者您可以修改加入表格的方式:

SELECT pm.team,
       pm.username,
       count(DISTINCT if(offer_pm.revenue>0.0,adv.adv_name,NULL)) AS adv_count,
       sum(offer_pm.click),
       sum(offer_pm.install),
       sum(offer_pm.revenue),
       sum(offer_pm.cost)
FROM pm
INNER JOIN offer_pm_adv_day offer_pm ON offer_pm.pm_id=pm.id
    AND offer_pm.logdate BETWEEN '2016-01-01' AND '2017-01-01'
INNER JOIN advertiser adv ON offer_pm.adv_id=adv.id
GROUP BY pm.team,
         pm.username

【讨论】:

    猜你喜欢
    • 2011-07-13
    • 2011-12-02
    • 1970-01-01
    • 2016-04-27
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    相关资源
    最近更新 更多