每个用户都可以投票选出任何视频,目前我们正在使用mysql,但现在我们在一个表中有超过2亿行,其中包含以下字段:
id
user_id # the voter
video_id # voted video
author_id # author of the video
state # 1 for normal and 0 for cancelled, maybe others
created_at
最常见的查询是获取特定视频的选民,但也许某些作者的视频选民或某些用户投票的视频也需要,通常按时间排序。
我应该将表格分成100个分片(通过video_id)还是使用ssdb?
如果我选择前者,为了按author_id或user_id查询,数据必须多次存储。
如果我选择ssdb,我认为我应该使用有序集并将时间戳存储为分数进行排序,并为每个用户或视频分配几个键,以便按不同字段查询并处理不同的状态。并且很难更改代码并迁移数据。
答案 0 :(得分:1)
有同样的困惑。 我所做的就是一起使用它们:
毫无疑问,更多的Redis密钥会带来更多的复杂性,但是必须有一个缓存模块来减少对MySQL的查询。
因为我只是使用Redis作为缓存,所以其中的数据可以随时丢弃:我可以使用MySQL中的数据在Redis中设置新的数据结构。
我个人不想只将所有数据都放在Redis中:内存比IAAS上的硬盘贵得多。
希望这有助于:)
答案 1 :(得分:0)
如果你使用MySQL,你需要一些关于细节的建议......
CREATE TABLE Votes (
# id -- no need for this
user_id INT UNSIGNED NOT NULL, # the voter
video_id INT UNSIGNED NOT NULL, # voted video
author_id INT UNSIGNED NOT NULL, # author of the video
state TINYINT UNSIGNED (or ENUM) NOT NULL, # 1 for normal and 0 for cancelled, maybe others
created_at TIMESTAMP NOT NULL,
PRIMARY KEY(video_id, user_id), -- see note
+ some indexes; see below
) ENGINE = InnoDB;
目前还不清楚唯一识别记录的内容。我猜到了什么,但我假设用户只能投票一次。
INT UNSIGNED
假设您赢得的筹码超过40亿。它需要4个字节,而不是8个字节的BIGINT
。如果您不希望特定事物需要16M以上的ID,请使用MEDIUMINT UNSIGNED
(仅3个字节)。
"最常见的查询是获取特定视频的选民。" (不是"投票数"?)
SELECT user_id FROM Votes WHERE video_id = ?;
# INDEX(video_id, user_id) -- not needed, assuming the PK specified above.
-- or
SELECT user_id FROM Votes WHERE video_id = ? ORDER BY created_at;
INDEX(video_id, created_at, user_id)
"但也许某些作者的视频选民" (好像video_id
在这里无关紧要):
SELECT user_id FROM Votes WHERE author_id = ?;
INDEX(author_id, user_id)
-- or
SELECT user_id FROM Votes WHERE author_id = ? ORDER BY created_at;
INDEX(author_id, created_at, user_id)
"或某些用户投票的视频也是必需的,通常按时间排序。"
SELECT video_id FROM Votes WHERE user_id = ? ORDER BY created_at;
INDEX(user_id, created_at, video_id)
根据这些建议,查询将非常快。此外,MySQL将自己进行缓存,因此添加另一个缓存层可能不会有帮助(特别是如果它抢占RAM)。
该表格需要几GB。