5

我想知道存储的最佳方法是什么,例如languages在一个user表中,当用户可以拥有任意多的语言时,希望不使用序列化数据,因为该字段将被密集搜索。

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

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

4

5 回答 5

5

这称为数据库规范化。具体来说,您需要映射“多对多”关联

你需要 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 个用户和几百种语言,这对磁盘使用率来说是一个巨大的改进(也许在我们这个时代,这不再是真的,我稍后会谈到)。这解决了磁盘问题,但我们仍然有搜索问题。同样,您如何让所有用户使用“西班牙语”语言?好吧,使用这种设计,您应该遍历 users 表并获取语言列,将其拆分为 ";" 并寻找 id 1。

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

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

大免责声明

正如我之前所说,有几种方法可以做到这一点。这取决于您的情况以及您想要达到的目标。如果您想根据该列进行搜索(例如,给我说英语的用户),您应该考虑我在答案顶部告诉您的设计。

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

关于联接

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

于 2012-04-06T17:33:10.837 回答
1

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

于 2012-04-06T17:31:23.027 回答
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)

有了这样的限制,用户可以根据需要分配尽可能多的语言。

于 2012-04-06T17:32:13.057 回答
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 存储了哪些用户知道哪些语言的关联。

于 2012-04-06T17:33:39.307 回答
0

我认为你应该考虑有两张桌子。一个与users一个与languages。它更容易维护,也更容易对joins这些表进行操作。

于 2012-04-06T17:32:00.610 回答