论坛帖子投票/观看的数据库模式,以及递增和显示视图数量的策略

时间:2009-12-22 03:45:37

标签: sql mysql database-design data-modeling database-schema

  

如果现在重要,我正在使用   MySQL / MyISAM,但我愿意使用   PostgreSQL的。我也愿意使用memcached。

考虑一个用于存储论坛帖子的表:

id forum_name post_date
1  Hey!       2009-01-01 12:00:00
  • 存储与线程相关的实体(如投票,视图和计数器)的最佳做法是什么?

我应该......

创建一个单独的表,例如

id thread_id views
1  1         532

或者将它保存为初始线程表中的列?

id forum_name post_date              views
1  Hey!       2009-01-01 12:00:00    532

另一个相关的小问题,显示和增加页面浏览量的实用解决方案是什么?我读了这个thread,似乎我只能缓存一段时间的值,我对增量部分并不十分清楚 - 可能就像将值存储在某个地方的平面文件中一样,然后定期用cronjobs更新每小时左右数据库论坛的观点?

修改 为了澄清,投票就像SO一样,每个线程一票,并且可以有逆转。没关系我对柜台的意思。

2 个答案:

答案 0 :(得分:8)

投票

我建议除了线程表之外还定义两个表 - VOTE_CODESTHREAD_VOTES。一目了然,它可能看起来过于标准化,但格式将允许您更改投票值而无需重大DML更改。

VOTE_CODES

  • vote_code,主键,IE:向上,向下
  • vote_cast_value - 归因于上/下投票的价值
  • vote_caster_value - 选项,如果你想保持反对施法者的反对票的风格。

THREAD_VOTES

  • thread_id
  • user_id
  • vote_code

THREAD_VOTES中的所有列都是主键 - 这将确保给定用户和线程的行数与投票代码一样多。假设只有两个代码,这将支持反转投票的能力,因为只有两条记录 - 一条带有任何代码。

浏览

我建议存储:

  • 线程ID
  • ip address
  • user_agent - 通过浏览器捕获
  • 时间戳

以上所有都是主键。您的表格将快速填充,但它将使您能够在视图中创建计算列以获得更准确的报告。

答案 1 :(得分:1)

平面文件显然是一个坏主意,因为你需要实现锁定(数据库已经这样做,并且该代码中的错误更少)。

关系数据库设计更像是一门艺术,而不是一门科学:你可以拥有

CREATE TABLE threads (
  tid THREADID
, title THREADTITLE
, views COUNTER
, PRIMARY KEY (tid)
);

并且它不会比

更“正确”
CREATE TABLE threads (
  tid THREADID
, title THREADTITLE
, PRIMARY KEY (tid)
);

CREATE TABLE views (
  tid THREADID
, views COUNTER
, PRIMARY KEY (tid)
, FOREIGN KEY (tid)
  REFERENCES threads
);

所以这取决于你。

我会说:首先选择最简单的事情,如果你发现它是必要的话会让它变得更复杂(例如出于性能原因)。 IOW:将views COUNTER属性放在threads中。如果事实证明trafic损害了性能(threads.views属性上的更新太多意味着dbms必须在其他属性中改变其他不可变数据),你总是可以将表拆分为两个,并将其替换为一个加入它们的视图。瞧,从易失性数据中分离出不可变(或很少变化)的数据,界面保持不变。

当然,请使用PostgreSQL。上面显示的代码在dbms中有效,只需添加以下内容:

CREATE DOMAIN threadid
AS INT NOT NULL;

CREATE DOMAIN threadtitle
AS TEXT NOT NULL
CHECK (LENGTH(VALUE) > 0);

CREATE DOMAIN counter
AS INT NOT NULL
CHECK (VALUE > 0);

编辑以反驳OMG小马的评论:当然这是安全的。

UPDATE threads SET
  views = views + 1
WHERE tid = X

成功或拯救。

编辑2 以添加投票方面的考虑因素

让我们说规则是:用户可以向线程投票(+1)或向下投注(-1),他或她在给定线程上的投票总和不得超过| 1 |,且历史记录无关紧要。如果用户可以投票给一个帖子,然后向下重置他们的投票“无投票”,然后又重新投票到“投票”,等等。

CREATE DOMAIN vote
AS INT NOT NULL
CHECK (VALUE BETWEEN -1 AND 1);

CREATE TABLE votes (
  tid THREADID
, uid USERID
, vote VOTE
, PRIMARY KEY (tid, uid)
);
在MySQL中,你可以

INSERT INTO votes (
  tid
, uid
, vote
) VALUES (
  X
, Y
, Z -- +1 or -1
)
ON DUPLICATE KEY UPDATE
vote = vote + Z
唉,PostgreSQL还没有内置这样的功能,所以你需要使用idiomatic user-level implementation