mysql查询需要46秒 - 需要更高效

时间:2015-01-28 16:36:26

标签: mysql

我已经到达了一个查询,它给了我想要的东西,但效率不高,执行时间超过45秒。如何修改以使其更快?

SELECT * 
FROM   (SELECT DISTINCT email, 
                    title, 
                    first_name, 
                    last_name, 
                    'chauntry' AS source, 
                    post_code  AS postcode 
    FROM   chauntry 
    WHERE  mailing_indicator = 1) AS x 
   LEFT JOIN (SELECT email, 
                     Avg(amount_paid)                AS avg_paid, 
                     Count(*)                        AS no_times_booked, 
                     Count(DISTINCT( Month(added) )) AS unique_months 
              FROM   chauntry 
              WHERE  added >= Now() - INTERVAL 1 year 
              GROUP  BY email) AS y 
          ON x.email = y.email

这是数据字段 enter image description here

这是我追查的列标题 enter image description here

3 个答案:

答案 0 :(得分:0)

为了帮助您提高性能,您确实需要索引。由于您实际上在运行两个不同的查询,因此我的CHAUNTRY表上会有以下索引

首先......首先让mailing_indicator,你直接跳到那些,然后收到电子邮件,这是加入后的基础。你实际上可以扩展索引以包括title,first,last,post_code作为覆盖索引,但这可能是过度的。

( mailing_indicator, email )

您的LEFT JOIN查询,无论mailing_indicator状态如何,您似乎都需要count,avg等。为了帮助优化这个,我会有一个索引

( added, email, amount_paid )

这将是一个覆盖索引,因此引擎不需要转到原始数据页来查询数据,而是直接从索引中获取它们。

关于您的不同月份数量的另外一个注释。你可能会错过一个计数条目。考虑一下月中,例如现在的1月28日。

如果您有2014年1月29日和2015年1月27日的参赛作品,它们将与1相同,而不是2代表两个不同的月份,因为它们跨越月份和年份。您可能希望将其更改为

DATE_FORMAT(added, '%M %Y') as unique_months_yrs

Syntax to create index

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
    [index_type]
    ON tbl_name (index_col_name,...)
    [index_type]

Create index Chauntry_MailInd_EMail on Chauntry ( mailing_indicator, email );
Create index Chauntry_Add_Email_Paid on Chauntry  ( added, email, amount_paid );

答案 1 :(得分:0)

DRapp,感谢详细的反馈 - 关于日期的疏忽。

我们是否正在谈论类似下面的内容以加快我的查询速度?我找不到有关创建覆盖索引的大量信息,下面的内容可疑。

ALTER TABLE `chauntry` 
  ADD INDEX(`mailing_indicator`, `email`); 

ALTER TABLE `chauntry` 
  ADD INDEX covering_index (`added`, `email`, `amount_paid`);  

答案 2 :(得分:0)

在第一个子查询中使用SELECT DISTINCT,在第二个子查询中使用GROUP BY。 这具有相同的效果。

from子句中的子查询通常是多余的,它们会生成未编制索引的派生表。当您对查询运行说明时,您将在执行计划中看到4个表格。这可以重写为没有子查询的查询:

SELECT x.email, 
    x.title, 
    x.first_name, 
    x.last_name, 
    'chauntry' AS source, 
    post_code  AS postcode,
    Avg(y.amount_paid) AS avg_paid, 
    Count(y.email) AS no_times_booked, 
    Count(DISTINCT( Month(y.added) )) AS unique_months
FROM
    chauntry x
LEFT JOIN
    chaunrty y
    ON x.email = y.email AND y.added >= CURRENT_DATE - INTERVAL 1 YEAR
GROUP BY x.email

但是,您的模型未正确规范化,您应该有两个表,一个包含帐户数据,另一个包含付款