我有一个MySQL查询,该查询对通过某些过滤器(时间过滤器和免费搜索)的电子邮件数量进行计数
该查询当前在我的服务器上至少需要30秒(时间间隔仅为12天),因此我想提高查询效率。
我对MySQL没有太多经验,所以请对我保持温柔。
当前查询是:
SELECT
count(distinct emls.EML_ID) as count FROM origins
JOIN emls ON emls.EML_ID = origins.source_id
JOIN email2addresses ON emls.EML_ID = email2addresses.EML_ID
JOIN email_addresses ON email_addresses.Email_ID = email2addresses.Email_ID
JOIN files ON files.Origin_ID = origins.Origin_ID
JOIN unique_files ON unique_files.Unique_File_ID = files.Unique_File_ID
WHERE origins.insert_date BETWEEN FROM_UNIXTIME(1533323333) and FROM_UNIXTIME(1534323333)
and (origins.source_id LIKE "%%" or emls.Subject LIKE "%%"
or email_addresses.Email_Address LIKE "%%" or files.File_Name LIKE "%%"
or files.File_ID LIKE "%%" or unique_files.File_Hash LIKE "%%");
在查询前运行explain
时,我得到:
1 SIMPLE origins index PRIMARY,Source_ID_index Source_ID_index 5 10699008 11.11 Using where; Using index
1 SIMPLE emls eq_ref PRIMARY PRIMARY 4 origins.Source_ID 1 100.00
1 SIMPLE files ref Unique_File_ID_index,Origin_ID_index Origin_ID_index 5 origins.Origin_ID 1 100.00 Using where
1 SIMPLE unique_files ref PRIMARY PRIMARY 4 files.Unique_File_ID 1 100.00
1 SIMPLE email2addresses ref EML_ID_index,Email_ID_index EML_ID_index 5 origins.Source_ID 4 100.00 Using where
1 SIMPLE email_addresses eq_ref PRIMARY PRIMARY 4 email2addresses.Email_ID 1 100.00 Using where
我在查询中所做的基本上是建立一个巨大的表(许多联接),然后在该巨大的表上应用过滤器,我认为这确实是一种不好的做法。
更具体地说,问题是:
我该如何重写此查询,以便
首先,时间过滤器将应用于origins
表,然后所有联接才对部分origins
表生效(仅在与时间过滤器匹配的记录上)?
在explain
输出的第一行,我在row
下得到值10699008
,这是MySQL需要通过的预期记录数,对?如果我正确理解应该尝试降低速度以提高速度,那么是否有关于此操作的最佳实践?
我还应该对这个查询进行其他改进以使其更快吗?
谢谢。