我想知道什么是最好的存储方式,例如languages
在user
表格中,当用户可以根据自己的意愿选择尽可能多的语言,并希望而不使用序列化数据,因为该字段将被严格搜索。Mysql在表格中存储任意数量的值的最佳方式
我想limtating条目的数量,为为例maximun 4语言,在user表中有语言1,LANG2 ..
有没有更好的方式来实现这一目标?
我想知道什么是最好的存储方式,例如languages
在user
表格中,当用户可以根据自己的意愿选择尽可能多的语言,并希望而不使用序列化数据,因为该字段将被严格搜索。Mysql在表格中存储任意数量的值的最佳方式
我想limtating条目的数量,为为例maximun 4语言,在user表中有语言1,LANG2 ..
有没有更好的方式来实现这一目标?
它被称为database normalization。具体而言,您需要映射一个"Many to Many" association
您需要3个表格。
User(id, name)
Language (id, language_name)
User_Language(id,id_user,id_language)
要获取所有语言的用户ID 3:
SELECT l.language_name
FROM User u
JOIN user_language ul ON (u.id=ul.id_user)
JOIN Language l ON (l.id = ul.id_language)
WHERE u.id = 3
编辑:
两件事情是很重要的注意@silkAdmin。第一个,就像@ BryceAtNetwork23指出的那样,不需要在User_Language表上添加一个id。第二个是,你应该了解joins,特别是MySQL Joins(因为SQL在不同的数据库引擎中倾向于不同)。你挖一点点之后,你就可以看到,在之前的查询加入用户表也没有必要,也可以简化为:
SELECT l.language_name
FROM user_language ul
JOIN Language l ON (l.id = ul.id_language)
WHERE ul.user_id = 3
我又补充它的第一个答案,使对你来说更容易。
为什么使用的语言表
我的回答只是反映我会做到这一点。有很多方法来实现要求的东西。说,我解释我自己。
让我们在极端思考。第一个极端是将语言存储在用户表中,如上所述。例如,我们可以有一列,并用分号分隔这些值。像这样的东西
User: (1, "John", "spanish;english;japanese")
这样做的好处是你不需要任何连接。鉴于你的用户的ID,你可以得到的语言。缺点是,这将是非常痛苦的搜索。如何让所有用户使用语言“西班牙语”? (这里的底线是你不能索引你的数据)。另一个缺点是,过时使用磁盘空间。在数据库和规范化发明的时候,磁盘空间确实很昂贵。因此,存储此:
User: (1, "John", "spanish;english;japanese")
User: (2, "Mary", "spanish;english")
这是不能容忍的东西。所以,有些人来了,说:“嘿,让我们使用IDS,所以,我们可以把它变成”:
User: (1, "John", "1;2;3")
User: (2, "Mary", "1;2")
Language (1,"spanish")
Language (2,"english")
10.000用户和语言仅有几百,这是对磁盘使用一个巨大的进步(也许在我们这个时代,这不再是真的,我会在稍后谈到)。这解决了磁盘问题,但我们仍然有搜索问题。同样,如何让所有用户使用语言“西班牙语”?那么,利用这个设计,你应该遍历用户表并获取语言列,将它分成“;”并查找ID 1.
这就是为什么我们开始使用的方法,我之前向您展示。
所以,到目前为止,一切顺利。相当不错的解释;)
大免责声明
正如我以前说过的,有几种方法可以做到这一点。这取决于你的情况,你想达到什么目的。如果您想根据该专栏进行搜索(例如,给我说英语的用户),您应该考虑我在答复顶部告诉您的设计。
现在有数据解决方案的“新浪潮”是被称为无SQL数据库(有异),尝试非规范化的数据。如果你担心模式的过度规范化,你应该看看这个。我建议你使用MongoDB和CouchDB,因为这些比较容易。
关于加入
不要担心2加入了性能。如果你有性能问题,那不是这个。数据库引擎是为此创建的。有了良好的内存缓存和索引优化,它应该可以顺利运行。
是的,最好的方法是使用列lang_id
和user_id
的附加表。您可以存储任意数量的用户/语言关联(每行一个)。
我认为你应该考虑有两张桌子。一个与users
和一个与languages
。维护起来更容易,对这些表执行joins
更容易。
创建表user_languages
user_id int,
language_id int,
与约束:
PRIMARY KEY (user_id, language_id),
FOREIGN KEY (language_id) REFERENCES language(id),
FOREIGN KEY (user_id) REFERENCES users(id)
有了这样的限制,用户可以根据需要分配有尽可能多的语言。
我认为实现这一目标的最好办法,就是有一个用户表USER_LANGUAGES表和语言表。这样,用户可以拥有任意数量的语言。
USER
user_id int
user_name varchar
USER_LANGUAGES
user_id int
lang_id int
LANGUAGES
lang_id int
lang_name varchar
USER存储基于用户的字段。语言存储每种特定语言(英语,德语等)的数据。 USER_LANGUAGES存储哪些用户知道哪种语言的关联。
其实,你就不需要在USER_LANGUAGE一个ID字段。字段id_user和id_language(一起作为连接的键)将确保唯一性。 – Aaron 2012-04-06 17:38:55
是的,但这是一个很好的做法。我不需要那个连接中的用户表,但为了解释我添加它。 – santiagobasulto 2012-04-06 18:06:40
@santiagobasulto感谢您的详细解答。我知道如何使用连接,但通过保持性能,我尝试只有在没有其他方式时才使用它们。虽然我很好奇为什么要使用语言表?不应该用户语言表足够了(用enum字段替换id_language) – silkAdmin 2012-04-07 01:24:08