我正在构建一个电子邮件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计数?
答案 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