【问题标题】:mysql using temporary table with subqueries, but not group by and order bymysql使用带有子查询的临时表,但不是group by和order by
【发布时间】:2012-05-01 05:37:57
【问题描述】:

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

让我感到困惑的是 MySQL 文档说,使用临时性通常是由 group by 和 order by 引起的,我都没有使用。子查询是否会导致隐含的 group by 或 order by?无论 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 |
+----+--------------------+----------+------+---------------+------+---------+------+------+------------------------------+

谢谢! 菲尔

【问题讨论】:

    标签: mysql explain


    【解决方案1】:

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

    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 子句对您来说大大减慢了速度,最后一个就足够了。

    【讨论】:

    • 非常感谢。以这种方式接近查询完全解决了延迟问题。很惊讶我没有想到这个查询写得多么尴尬。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    相关资源
    最近更新 更多