9

我正在尝试为以下问题找到最佳解决方案:需要设计一个数据库(基于postgres),其中包含触发器和计数器系统,它将形成一个有效查询、更新和存储信息的系统'显示在页面上的每篇文章(或博客条目,或类似的东西)中存在多少未读评论'。

每个出现的解决方案都有一些严重的缺点,无论是在查询、存储还是更新部分。即它需要太多的存储空间,或者太多的更新,或者太昂贵的查询。

你的经历呢?也许对于这类问题已经形成了很好的解决方案?

4

5 回答 5

9

我会尽可能简单地保持模式,因此查询将尽可能简单。这通常也具有最低的存储要求。当然,设置索引来支持这个查询。

下一步:测量性能!“衡量就是知道。” 响应时间是多少?服务器的负载是多少?只要性能是可以接受的,保持模式和查询简单。如果不是绝对必要,请不要牺牲可维护性:您的继任者稍后会感谢您。

如果性能确实是个问题,请查看您用于应用程序的框架的缓存功能。不执行查询总是比执行优化查询快。

于 2009-01-17T09:57:58.703 回答
4

如果你真的没有在你的资源范围内取得成功,也许你必须调整用户体验。也许存储最后一次访问线程的日期就足够了。

于 2009-01-17T10:00:20.880 回答
4

我不相信典型的标准化方法会给您带来低效的查询。假设您有一个带有 PK 的表article_comments(article_id, comment_id)另一个comments_seen_by_user带有 PK的表(user_id, article_id, comment_id)。对于页面上列出的每篇文章,您需要做的就是:

SELECT count(*) FROM article_comments ac
WHERE article_id = ?                -- Parameter
AND NOT EXISTS (
    SELECT 1 FROM comments_seen_by_user csbu
    WHERE csbu.user_id = ?          -- Parameter
    AND   csbu.article_id = ac.article_id
    AND   csbu.comment_id = ac.comment_id
)

如果您在一页上显示 20 篇文章,您将运行上述查询 20 次,每次运行将使用一个索引从 中提取 10-20 行article_comments,而子查询测试只是对 的另一个索引扫描comments_seen_by_user,所以全部在您可能需要执行 20 * (20 * 2) = 800 次索引查找来显示给定页面。这对现代数据库来说并不费力。而且我可能忽略了 PostgreSQL 可能找到的更好的查询计划。

你有没有试过这个,发现性能不足?如果是这样,我的第一个猜测是你有一段时间没有VACUUM编辑了。否则,我对每页文章数量或每篇文章评论数的估计一定是错误的——在这种情况下,请更新更多详细信息。

于 2009-01-17T10:50:14.040 回答
1

我将第二个 j_random_hacker 的答案,只是我会避免将 article_id 存储在 comments_seen_by_user 表中,因为每条评论的 comment_id 应该是全局唯一的。此外,PostgreSQL 中的 3 维(和 2 维程度较低)索引仍然很慢,因此请尽量避免使用它们。

围绕 user_id、comment_id 值的表没有真正好的方法来存储有关阅读评论的信息,只需确保它具有唯一索引即可。这样的表中几千万行对PostgreSQL来说完全没有问题,只要它可以将索引保留在内存中。您可以通过查询系统表来跟踪索引大小(磁盘上 8KB 页面的数量):

select relname,relpages from pg_class where relname='comments_seen_by_user_pkey';
于 2009-01-17T11:05:38.237 回答
0

我同意采用标准化方法,看看是否可行。通常我应该。但是,您也可以在“评论”表上使用一些 INSERT 触发器,它会更新基本(即文章)表中的评论计数器。这取决于该网站的使用情况:如果大多数人阅读评论(与添加评论相比),则基于触发器的方法的开销应该会迅速摊销。如果它是一个具有高评论负载的网站,这可能会影响性能。

当您有一些合理的使用配置文件时,我会选择一个简单的规范化表结构并在以后添加其他优化。

于 2009-01-17T12:01:25.613 回答