flat files are obviously a bad idea, because you'd need to implement locking (the db already does that, and there's fewer bugs in that code).
relational database design is more of an art rather than a science: you can have
CREATE TABLE threads (
tid THREADID
, title THREADTITLE
, views COUNTER
, PRIMARY KEY (tid)
);
and it'll be no more and no less "correct" than
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
);
so it's really up to you.
i'd say: go with the simplest thing first, make it more complicated if you find it's necessary (e. g. for performance reasons). IOW: put the views COUNTER
attribute in threads
. if it turns out the trafic is hurting performance (too many updates on the threads.views
attribute mean the dbms must shuffle around otherwise immutable data in the other attributes), you can always split the table up in two, and replace it with a view that joins them. voila, immutable (or rarely changing) data separated from the volatile data, interface remains the same.
of course, go with PostgreSQL. the above shown code is valid in that dbms, just add these:
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);
edit to refute the comment by OMG Ponies: of course it's safe.
UPDATE threads SET
views = views + 1
WHERE tid = X
either succeeds or bails out.
edit 2 to add consideration for the voting aspect
let's say the spec is: a user may vote a thread up (+1) or down (-1), the sum of his or her votes on a given thread may not exceed |1|, and the history is irrelevant. iow a user may vote a thread up, then down to reset their vote to "no vote", then down again to "voted down", etc.
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)
);
in MySQL, you could
INSERT INTO votes (
tid
, uid
, vote
) VALUES (
X
, Y
, Z -- +1 or -1
)
ON DUPLICATE KEY UPDATE
vote = vote + Z
alas, PostgreSQL doesn't (yet) have such functionality built in, so you'd need to use the idiomatic user-level implementation