Mysql 我如何在加入的InnoDB表上优化此计数?

Mysql 我如何在加入的InnoDB表上优化此计数?,mysql,count,distinct,innodb,Mysql,Count,Distinct,Innodb,。。。或者,“我们有多少独特的电子邮件打开?(在一般活动中)” 目前,在Amazon RDS实例上运行大约需要一分钟半的时间。所涉及表格的总行数大致如下: 活动:250 收件人:330000 浏览次数:53万 电邮:1380000 解释给我: SELECT COUNT(DISTINCT r.id) FROM views v INNER JOIN emails e ON v.email_id = e.id INNER JOIN recipients r ON e.recipient_id =

。。。或者,“我们有多少独特的电子邮件打开?(在一般活动中)”

目前,在Amazon RDS实例上运行大约需要一分钟半的时间。所涉及表格的总行数大致如下:

  • 活动:250
  • 收件人:330000
  • 浏览次数:53万
  • 电邮:1380000
解释给我:

SELECT COUNT(DISTINCT r.id)
FROM views v
INNER JOIN emails e ON v.email_id = e.id
INNER JOIN recipients r ON e.recipient_id = r.id
INNER JOIN campaigns c ON e.campaign_id = c.id
WHERE c.centre_id IS NULL;

我能做些什么来加快这个总数?

只有在
收件人.id
电子邮件.recipient\u id
之间没有强制外键约束,并且您想排除那些(不再)登记在
收件人
表中的收件人时,才需要加入
收件人。否则,直接从联接中省略该表;您可以使用
电子邮件.recipient\u id
而不是
recipients.id
。忽略加入应该是一个巨大的胜利

或者,从加入中省略
收件人
,因为它与提出的问题无关,这是关于打开的唯一电子邮件,而不是关于打开任何电子邮件的唯一收件人。在这种情况下,您应该能够从…
中选择COUNT(*),因为每个
电子邮件
行已经是唯一的

除此之外,看起来您已经很好地利用了索引,尽管我承认我发现
EXPLAIN PLAN
输出很难阅读,尤其是没有标题。尽管如此,您的查询似乎根本不读取基表,因此添加新索引不太可能有帮助

您可以尝试在查询中涉及的表上执行一个
优化表
,尽管这听起来可能比实际情况更有希望

您应该定期在此查询中涉及的表上运行
ANALYZE TABLE
,以使查询优化器尽可能选择最佳计划。不过,看起来优化器已经在选择一个合理的计划,所以这可能没有多大帮助


如果您仍然需要更好的性能,那么还有一些(包括移动到更快的硬件),但是它们太多了,这里无法讨论。

您希望MySQL能够利用
WHERE
子句立即限制结果集。为了做到这一点,您需要适当的索引来加入从活动到电子邮件,然后从电子邮件到收件人和视图的链接

在campaiments.center\u id上放置索引以帮助搜索(满足
WHERE
子句)。我假设magnities.id是该表上的主键

在emails.campaign\u id上放置索引,以帮助加入来自活动的电子邮件。将收件人id和电子邮件id添加到该索引以提供覆盖索引

现在,
EXPLAIN
结果应该按顺序显示表格,从活动开始,然后是电子邮件,然后是其他两个。MySQL仍然需要一个内部临时表来应用
DISTINCT
。你确定你需要吗?
我假设emails.id和recipients.id是主键。

我不明白r.id如何表示打开的电子邮件,也不明白为什么需要
不同的
。考虑添加一些示例数据来说明这个问题。抱歉,我的问题的措辞不清楚:“独特的电子邮件打开”不是开放邮件的计数,而是打开电子邮件的唯一接收者的计数。因此,查询需要计算收件人id——尽管正如John Bollinger在下面指出的那样,我可以通过计算电子邮件来保存一个连接。收件人id。我需要
不同的
,因为收件人可能会多次打开一封电子邮件,这是我想打折的。何时创建收件人记录?我想你知道你在用内部连接做什么。如果您使用的是email.recipient\u id,则可能是没有匹配收件人记录的记录。通常,您应该为这些类型的问题提供示例数据和所需的输出,否则,我们必须假设您知道如何处理查询。
1   SIMPLE  r   index   PRIMARY UNIQ_146632C4E7927C74   767 NULL    329196  Using index
1   SIMPLE  e   ref PRIMARY,IDX_4C81E852E92F8F78,IDX_4C81E852F639F774   IDX_4C81E852E92F8F78    111 ecomms.r.id 1   Using where
1   SIMPLE  v   ref IDX_11F09C87A832C1C9    IDX_11F09C87A832C1C9    111 ecomms.e.id 1   Using where; Using index
1   SIMPLE  c   eq_ref  PRIMARY,IDX_E3737470463CD7C3    PRIMARY 110 ecomms.e.campaign_id    1   Using where