mysql使用带子查询的临时表,但不是group by和order by

时间:2012-05-01 05:37:58

标签: mysql explain

我有以下mysql查询,大约需要3分钟才能运行。它有2个子查询,但表中只有很少的行。在做解释时,看起来“使用临时”可能是罪魁祸首。显然,看起来数据库正在为所有三个查询创建一个临时表,如下面的“使用临时”标识所述。

令我感到困惑的是MySQL文档说,使用临时文件通常是由group by和order by引起的,我都没有使用它。子查询是否会导致隐式组或按顺序排列?子查询是否导致临时表是必要的,无论是按组还是按顺序排列?有关如何重构此查询以便MySQL可以更有效地处理它的任何建议吗? MySQL设置中的任何其他调整想法?

mysql> explain
SELECT DISTINCT COMPANY_ID, COMPANY_NAME
  FROM COMPANY
 WHERE ID IN (SELECT DISTINCT ID FROM CAMPAIGN WHERE CAMPAIGN_ID IN (SELECT
              DISTINCT CAMPAIGN_ID FROM AD
              WHERE ID=10 AND (AD_STATUS='R' OR AD_STATUS='T'))
              AND (STATUS_CODE='L' OR STATUS_CODE='A' OR STATUS_CODE='C'));

+----+--------------------+----------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type        | table    | type | possible_keys | key  | key_len | ref  | rows | Extra                        |
+----+--------------------+----------+------+---------------+------+---------+------+------+------------------------------+
|  1 | PRIMARY            | COMPANY  | ALL  | NULL          | NULL |    NULL | NULL | 1207 | Using where; Using temporary |
|  2 | DEPENDENT SUBQUERY | CAMPAIGN | ALL  | NULL          | NULL |    NULL | NULL |  880 | Using where; Using temporary |
|  3 | DEPENDENT SUBQUERY | AD       | ALL  | NULL          | NULL |    NULL | NULL |  264 | Using where; Using temporary |
+----+--------------------+----------+------+---------------+------+---------+------+------+------------------------------+

谢谢! 菲尔

1 个答案:

答案 0 :(得分:3)

我不知道您的架构的结构,但我会尝试以下内容:

CREATE INDEX i_company_id ON company(id);   -- should it be a Primary Key?..
CREATE INDEX i_campaign_id ON campaign(id); -- same, PK here?
CREATE INDEX i_ad_id ON ad(id);             -- the same question applies
ANALYZE TABLE company, campaign, ad;

您的查询可以像这样简化:

SELECT DISTINCT c.company_id, c.company_name
  FROM company c
  JOIN campaign cg ON c.id = cg.id
  JOIN ad ON cg.campaign_id = ad.campaign_id
 WHERE ad.id = 10
   AND ad.ad_status IN ('R', 'T')
   AND ad.status_code IN ('L', 'A', 'C');
子查询中的

DISTINCT子句对你来说显着减慢了事情,最后一个就足够了。