mysql - 如何在连接的 InnoDB 表上优化此 COUNT DISTINCT?

标签 mysql count distinct innodb

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;

...或者,“我们打开了多少个独特的电子邮件?(针对一般营销事件)”

目前在 Amazon RDS 实例上运行大约需要一分半钟。涉及的表的总行数大致为:

  • 广告事件:250
  • 收件人:330,000
  • 观看次数:530,000
  • 电子邮件:1,380,000

解释给我:

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

我该怎么做才能更快地得到这个总数?

最佳答案

仅当您未在 recipients.idemails.recipent_id 之间强制执行外键约束时,您才需要加入recipients 并且您想要排除(不再)在recipients 表中列出的收件人。否则,立即从连接中忽略该表;您可以使用emails.recipient_id而不是recipients.id。省略 join 应该是一个巨大的胜利。

或者,从连接中省略收件人,因为它与所提出的问题无关,该问题与打开的唯一电子邮件有关,而不是与唯一有关收件人打开任何电子邮件。在这种情况下,您应该能够SELECT COUNT(*) FROM ...,因为每个emails行已经是唯一的。

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

您可以尝试对查询中涉及的表执行OPTIMIZE TABLE,尽管这听起来可能比实际情况更有希望。

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

如果您仍然需要更好的性能,那么有 other possibilities (包括转向更快的硬件),但它们太多了,无法在此讨论。

关于mysql - 如何在连接的 InnoDB 表上优化此 COUNT DISTINCT?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28093562/

相关文章:

mysql - 根据条件从其他 2 列中选择不同的一列(如何配对它们?)

facebook-graph-api - 如何计算 iOS sdk 中 Facebook 好友的数量?

MySQL 左连接 COUNT() 和 SUM() 与来自同一个表的 CASE

r - 使用 dplyr 对多个分组变量进行计数

sql - Oracle SQL - 从给定列表中选择不同的值

mysql - 如何在 SQL 中索引列表数据以快速搜索某些元素或元素组?

php - MySQL合并不同结构的表

SQL SUM 和 DISTINCT 两列

php - 自动提交复选框以保存到 MySQL

MYSQL 选择多个不同值的总和