平面文件显然是个坏主意,因为您需要实现锁定(数据库已经这样做了,并且该代码中的错误更少)。
关系数据库设计更像是一门艺术而不是一门科学:你可以拥有
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
. 如果事实证明流量正在损害性能(属性上的太多更新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 Ponies 的评论:当然是安全的。
UPDATE threads SET
views = views + 1
WHERE tid = X
要么成功,要么退出。
编辑 2以增加对投票方面的考虑
假设规范是:用户可以对线程投赞成票(+1)或反对票(-1),他或她对给定线程的投票总和不得超过|1|,并且历史是无关紧要的。iow 用户可以对线程投赞成票,然后投反对票以将其投票重置为“不投票”,然后再次投反对票以“投反对票”,等等。
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(还)没有内置这样的功能,所以你需要使用惯用的用户级实现