5

我正在一个带有简单规范化数据库的网站上工作。

有一个名为 Pages 的表和一个名为 Views 的表。每次查看 Page 时,该 View 的唯一记录都会记录在 Views 表中。

在网站上显示页面时,我使用一个简单的 MySQL COUNT() 来汇总显示的视图数。

数据库设计似乎很好,除了这个问题:我不知道如何检索数千个浏览次数最多的前 10 个页面。

我是否应该通过添加 Pages.views 列来保存每个页面的总视图数来非规范化 Pages 表?或者有没有一种有效的方法来查询前 10 个浏览次数最多的页面?

4

6 回答 6

9
   SELECT p.pageid, count(*) as viewcount FROM 
   pages p
   inner join views v on p.pageid = v.pageid
   group by p.pageid
   order by count(*) desc   
   LIMIT 10 OFFSET 0;

我无法对此进行测试,但可以进行类似的测试。除非由于性能限制而不得不存储值,否则我不会存储该值(我刚刚学习了“过早优化”一词,如果您这样做,它似乎也适用)。

于 2009-03-04T04:35:21.947 回答
3

这取决于您尝试维护的信息级别。如果你想记录谁在什么时候看过?然后单独的表就可以了。否则,视图列是要走的路。此外,如果您保留一个单独的列,您会发现该表将更频繁地被锁定,因为每个页面视图都会尝试更新其相应行的列。

Select pageid, Count(*) as countCol from Views
group by pageid order by countCol DESC
LIMIT 10 OFFSET 0;
于 2009-03-04T04:38:29.833 回答
2

数据库规范化是关于存储数据的最有效/最少冗余的方式。这有利于事务处理,但通常与再次有效获取数据的需求直接冲突。该问题通常通过具有更易于访问的预处理数据的派生表(索引、物化视图、汇总表...)来解决。这里的(有点过时的)流行词是数据仓库。

我认为您希望保持 Pages 表标准化,但有一个包含总数的额外表。根据这些计数需要多长时间,您可以在更新原始表时更新表,或者您可以让后台作业定期重新计算总数。

您还希望仅在确实遇到性能问题时才这样做,除非您有大量记录或大量并发访问,否则您不会这样做。保持您的代码灵活,以便能够在拥有表格和不拥有表格之间切换。

于 2009-03-04T04:37:25.703 回答
1

我可能会在 Pages 表中包含视图列。

对我来说,这似乎是一个完全合理的规范化突破。特别是因为我无法想象您会删除视图,因此您不会期望计数会失控。在这种情况下,参照完整性似乎不是超级关键。

于 2009-03-04T04:34:09.407 回答
0

在这种情况下,非规范化肯定会起作用。你的损失是额外的柱子用完了额外的存储空间。

或者,您可以设置一个计划的作业,以每晚填充此信息,只要您的流量较低,x 时间段。

在这种情况下,除非您手动运行此查询,否则您将无法立即了解您的页数。

非规范化绝对可以用来提高性能。

——克里斯

于 2009-03-04T04:38:18.103 回答
0

虽然这是一个老问题,但我想添加我的答案,因为我发现接受的问题被误导了。

对单个选定行进行 COUNT 是一回事。对所有列的 COUNT 进行排序是另一回事。

即使您只有 1000 行,每行都有一些连接,您也可以轻松地读取数万行,甚至数百万行。

如果你只是偶尔调用它是可以的,但否则它会非常昂贵。

你可以做的是添加一个触发器:

CREATE TRIGGER ins AFTER INSERT ON table1 FOR EACH ROW
UPDATE table2
SET count = count + 1
WHERE CONDITION
于 2021-05-29T15:18:07.693 回答