通过许多联接和过滤器优化MySQL查询

时间:2018-08-29 12:05:09

标签: mysql sql-execution-plan

我有一个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

我在查询中所做的基本上是建立一个巨大的表(许多联接),然后在该巨大的表上应用过滤器,我认为这确实是一种不好的做法。

更具体地说,问题是:

  1. 我该如何重写此查询,以便 首先,时间过滤器将应用于origins表,然后所有联接才对部分origins表生效(仅在与时间过滤器匹配的记录上)?

  2. explain输出的第一行,我在row下得到值10699008,这是MySQL需要通过的预期记录数,对?如果我正确理解应该尝试降低速度以提高速度,那么是否有关于此操作的最佳实践?

  3. 我还应该对这个查询进行其他改进以使其更快吗?

谢谢。

0 个答案:

没有答案