我在一个社交网站工作,所以我希望用户会很多。我需要为每个用户保存标签(key | counter),我想知道是否使用1)一个大表vs 2)一个真正的大表vs 3)分裂的大表更好。
1)这是许多表实现的一个例子
table userid_tags(每个用户都有自己的表)
key | counter
----- ---------
tag1 | 3
tag2 | 1
tag3 | 10
Query 1: SELECT * FROM userid_tags WHERE key='tag1'
Query 2: SELECT * FROM userid_tags
2)单表实现:
表标签key | counter | user_id
----- ------------------
tag1 | 3 | 20022
tag2 | 1 | 20022
tag2 | 10 | 31234
Query 1: SELECT * FROM userid_tags WHERE key='tag1' AND user_id='20022'
Query 2: SELECT * FROM userid_tags AND user_id='20022'
3)分裂表实现
table 1000_tags (user_id from 1 to 1000)
key | counter | user_id
----- ------------------
tag1 | 3 | 122
tag2 | 1 | 122
tag2 | 10 | 734
table 21000_tags (user_id from 20000 to 21000)
key | counter | user_id
----- ------------------
tag1 | 3 | 20022
tag2 | 1 | 20022
tag2 | 10 | 20234
Query 1: SELECT * FROM userid_tags WHERE key='tag1' AND user_id='20022'
Query 2: SELECT * FROM userid_tags AND user_id='20022'
问题3)什么是好的分割索引?我使用了1000(用户)遵循
2是正确答案。考虑一下如何维护每个用户一个表,或者每1000个标签一个表。如何创建/更新/删除表?如果你必须进行大量的改变呢?您如何能够找出需要从哪个表中进行选择?即使可以,如果需要同时从多个表中进行选择(例如获取两个用户的标签)该怎么办呢?
将表分开并不会给您带来太多的性能好处。这是真的,如果表增长非常大,插入可能会变慢,因为mysql必须创建键,但只要你有合适的键查找应该非常快。
另一个类似的解决方案是有一个用于标记的表,一个用于用户的表,以及一个映射这两者的表。这将保持标记基数较小,如果您对两个表使用auto_increment代理键,则两个表的键长度都将很小,这应该使查找尽可能快,而不受关系的限制(即必须找出其他用户要连接的其他表)。
使用选项2是处理此问题的正确方法。但是,您仍然可以在表中使用分区。所有关于使用分区的信息都可以在MySQL文档中找到。
为每1000个用户将表划分为多个分区,如下所示:
CREATE TABLE tags (`key VARCHAR(50), counter INT, user_id INT)
PARTITION BY KEY(user_id) partitions 1000;
如果user_id
是21001,您可以在正确的分区中开始搜索,例如:
SELECT * FROM tags PARTITION (p22);'
因为id 21001将在第22个分区中。查看链接获取更多信息