Mysql在表中存储任意数量值的最佳方法

时间:2012-04-06 17:28:10

标签: mysql database

我想知道什么是最好的存储方法,因为当用户可以拥有他想要的尽可能多的语言时,让我们在languages表中说user,并希望不使用序列化数据这个领域将被强烈搜索。

我在考虑限制条目的数量,例如,最大化4种语言,在用户表中有lang1,lang2 ..

有没有更好的方法来实现这一目标?

5 个答案:

答案 0 :(得分:5)

它被称为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在不同的数据库引擎中往往会有所不同)。在您再挖掘一下之后,您将能够看到在上一个查询中加入User表也是不需要的,可以简化为:

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")

这是一些无法容忍的事情。所以,有些人过来说:“嘿,让我们使用ID,所以,我们可以把它变成”:

User: (1, "John", "1;2;3") 
User: (2, "Mary", "1;2")

Language (1,"spanish")
Language (2,"english")

对于10.000个用户和几百种语言,这是磁盘使用量的巨大改进(可能在我们的时代,这不再是真的,我将在稍后介绍)。这解决了磁盘问题,但我们仍然存在搜索问题。再次,如何让您的所有用户使用“西班牙语”语言?好吧,使用这种设计,你应该迭代用户表并获取语言列,将其拆分为“;”并寻找id 1。

这就是为什么我们开始使用之前向您展示的方法。

所以,到目前为止一切顺利。很好的解释;)

大免责声明

正如我之前所说,有几种方法可以做到这一点。这取决于你的情况,你想要实现什么。如果你想搜索该栏目(例如,给我说英语的用户),你应该考虑我在答案顶部告诉你的设计。

现在有一种称为no-sql数据库(它变化)的数据解决方案的“新浪潮”试图对数据进行非规范化。如果您担心模式的过度规范化,那么您应该看看它。我推荐你MongoDB和CouchDB,因为那些更容易入手。

关于加入

不要担心2个连接的性能。如果你遇到性能问题,那就不是这个了。数据库引擎就是为此而创建的。凭借良好的内存缓存和索引优化,它应该可以顺利运行。

答案 1 :(得分:1)

是的,最好的方法是使用包含lang_id列和user_id列的附加表格。在那里,您可以存储任意数量的用户/语言关联(每行一个)。

答案 2 :(得分:1)

创建表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)

通过这些限制,用户可以根据需要分配多种语言。

答案 3 :(得分:1)

我认为实现这一目标的最佳方法是拥有一个USER表,一个USER_LANGUAGES表和一个LANGUAGES表。这样,用户可以拥有任意数量的语言。

USER
user_id int
user_name varchar

USER_LANGUAGES
user_id int
lang_id int

LANGUAGES
lang_id int
lang_name varchar

USER存储基于用户的字段。 LANGUAGES存储每个特定语言的数据(英语,德语等)。 USER_LANGUAGES存储哪些用户知道哪种语言的关联。

答案 4 :(得分:0)

我认为你应该考虑有两张桌子。一个users,一个languages。它更容易维护,并且更容易对这些表格joins