我有2个表 posts
<id, user_id, text, votes_counter, created>
和 votes
<id, post_id, user_id, vote>
。表格投票可以是1(upvote)或-1(downvote)。现在,如果我需要在帖子上获取总票数(upvotes - downvotes),我可以通过两种方式完成。
count(*)
从votes
表中计算该帖子的upvotes和downvotes的数量,然后进行数学计算。votes_counter
,并在每次用户upvotes或downvotes时递增或递减。然后只需提取votes_counter
。我的问题是哪一个更好,在什么条件下。通过说条件,我的意思是可扩展性,峰值时间等因素。
据我所知,如果我使用方法1,对于包含数百万行的表, count(*)
可能是一个繁重的操作。为了避免这种情况,如果我在高峰期使用计数器,则vote_counter列可能会死锁,有太多用户试图更新计数器!
第三种方法是否比两种方式都更好并且实施起来很简单?
答案 0 :(得分:4)
这两种方法代表了实施复杂性和速度之间的共同权衡。
第二种方法很快就会变得非常复杂:
我将从第一种方法开始,看看它的表现如何。然后我会尝试使用索引进行优化。最后,我会考虑使用第二种方法,可能会编写触发器来自动更新计数。
答案 1 :(得分:1)
由于这听起来很像StackExchange,我会在元数据中引用您关于网站上使用的数据库模式的this answer。投票表如下所示:
投票表:
Id
PostId
VoteTypeId
,以下值之一:
1 - AcceptedByOriginator
2 - UpMod
3 - DownMod
4 - Offensive
5 - Favorite (if VoteTypeId = 5, UserId will be populated)
6 - Close
7 - Reopen
8 - BountyStart (if VoteTypeId = 8, UserId will be populated)
9 - BountyClose
10 - Deletion
11 - Undeletion
12 - Spam
15 - ModeratorReview
16 - ApproveEditSuggestion
UserId
(仅在VoteTypeId为5或8时出现)
CreationDate
BountyAmount
(仅在VoteTypeId为8或9时才出现)所以基于它听起来就像它的运行方式是:
SELECT VoteTypeId FROM Votes WHERE VoteTypeId = 2 OR VoteTypeId = 3
然后根据价值,做数学:
int score = 0;
for each vote in voteQueryResults
if(vote == 2) score++;
if(vote == 3) score--;
即使有数百万的结果,这可能是一个非常快速的操作,因为它很简单。