我已经到达了一个查询,它给了我想要的东西,但效率不高,执行时间超过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
这是数据字段
这是我追查的列标题
答案 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
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
但是,您的模型未正确规范化,您应该有两个表,一个包含帐户数据,另一个包含付款