2009-03-04 82 views
4

我正在一个简单的标准化数据库的网站上工作。总数应该是非规范化的吗?

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

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

数据库设计看起来很好,除了这个问题:我在如何检索数千人中浏览量最高的10个页面时感到不知所措。

我是否应该通过添加Pages.views列来保持每个页面的总视图数量来对Pages表格进行非规范化处理?或者有没有一种有效的方式来查询前10个最常浏览的页面?

回答

8
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; 

我无法测试这个,但沿着这些线。除非由于性能限制(我刚刚学习术语“过早优化”,而且如果您这样做似乎适用),否则我不会存储该值。

+1

+1表示在性能问题出现之前不存储总数。 – Thilo 2009-03-04 04:40:59

1

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

这似乎是一个完全合理的正常化突破给我。特别是因为我无法想象你删除视图,所以你不会指望计数失控。在这种情况下,参照完整性似乎不是超关键。

1

数据库规范化是关于存储数据的最有效/最不重复的方式。这对于事务处理很有用,但通常直接与需要有效地再次获取数据的冲突。这个问题通常通过派生表(索引,物化视图,汇总表......)来解决,并且具有更易于访问的预处理数据。这里(稍微过时)的流行语是数据仓库。

我认为你想保持你的页表正常化,但有一个额外的表与总数。根据这些计数的最新数据,您可以在更新原始表格时更新表格,也可以让后台作业定期重新计算总计。

只有在真正遇到性能问题时才会这样做,除非拥有大量的记录或大量的并发访问,否则不会这样做。保持你的代码的灵活性,以便能够在表格和不具有表格之间切换。

0

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

或者,您可以设置一项计划作业,以在夜间基础上填充此信息,只要您的流量低,x时间段。

在这种情况下,除非手动运行此查询,否则您将失去立即知道页面计数的能力。

反规范化肯定可以用来提高性能。

--Kris

+0

损失既是额外的列,也是需要保持一致。我同意在这种情况下这是合理的。 – thomasrutter 2009-03-04 04:43:08

3

它依赖于信息化水平,你正试图保持。如果你想记录谁看过什么时候?然后单独的表格很好。否则,视图列是要走的路。另外,如果您保留一个单独的列,您会发现该表会更频繁地锁定,因为每个页面视图都会尝试更新相应行的列。

Select pageid, Count(*) as countCol from Views 
group by pageid order by countCol DESC 
LIMIT 10 OFFSET 0;