数据库模式,用于统计每个邮箱的未读电子邮件

时间:2019-04-29 18:39:12

标签: mysql sql mariadb

我正在构建一个电子邮件Web应用程序,但是在想出一个架构时会遇到麻烦,该架构可以快速为我提供每个文件夹的未读电子邮件计数。

此刻我的模式如下:

CREATE TABLE emails(id INT, user_id INT, folder INT, 
    read_on TIMESTAMP, raw_email_filename VARCHAR(128));

要获取每个文件夹的未读计数,我可以运行以下查询:

SELECT count(*) FROM email WHERE user_id =? AND folder IN (?..) AND read_on IS NULL;

但是,鉴于我的索引是(user_id, folder),这必须遍历每个文件夹上的所有电子邮件才能获得计数。

我当时正在考虑添加索引(user_id, folder, read_on),但是当我只对read_on的{​​{1}}值感兴趣时,这对于NULL来说条目太多了。

有更好的方法吗?也许与非规范化?继续使用Redis计数?

1 个答案:

答案 0 :(得分:0)

我会考虑

INDEX(user_id, read_on, folder)

建立最佳索引的准则是首先列出用=(如此计数IS NULL进行测试的列,然后列出INs({{ 1}}),然后是一个范围(您没有任何范围)。

不用担心folder条目的索引条目的浪费;他们使磁盘杂乱无损,而不会影响性能。

另一方面,当您更改read_on IS NOT NULL(通过read_on?)时,由于我建议的UPDATE中的条目需要从一个位置移动到另一个位置,因此略有打击在索引BTree中。同样,这可能不值得担心。

您不想要INDEX吗?

GROUP BY

执行SELECT folder, COUNT(*) FROM emails WHERE user_id = ? AND folder IN (...) AND read_on IS NULL GROUP BY folder; 。对于我的EXPLAIN SELECT ...INDEX可能会说EXPLAIN,表示“覆盖”索引。这就是所需的所有列在索引中的位置。

有关创建索引的更多信息:http://mysql.rjweb.org/doc.php/index_cookbook_mysql