在MySQL中存储用户设置的最佳方式


Best way of storing user settings in MySQL?

我只是想知道为我的web应用程序存储用户特定设置的最佳方式是什么?只是用户可能有的偏好。我想到了两个选择:

  1. Users table -我将为我的用户创建一个表。创建名为"preferences"的列,并在其中以键=>值对的形式存储序列化的数据

  2. Settings table -有一个单独的名为Settings的表,其中包含user_id列。以相同的方式保存设置

任何输入将是感激的。谢谢:)!

,

编辑:只是补充一下,如果我没有序列化/json或任何数据放入数据,我必须为每个设置有一列。

对于任何总是每个用户设置的,您应该倾向于将其保留在Users表中,按照通常的规范化。至于可选配置,我倾向于喜欢下面的表结构:

TABLE Users:
  id INT AI
  name VARCHAR
  ...
TABLE User_Settings
  user_id INT PK,FK
  name VARCHAR PK
  type BOOL
  value_int INT NULL
  value_str VARCHAR NULL

其中User_Settings.type指定要引用的是整数还是字符串字段。

ie:

INSERT INTO Users (id, name) VALUES (1, 'Sammitch');
INSERT INTO User_Settings (user_id, name, type, value_int) VALUES (1, 'level', 1, 75);
INSERT INTO User_Settings (user_id, name, type, value_str) VALUES (1, 'lang', 0, 'en');

对于INSERT/UPDATE问题:

INSERT INTO User_Settings (user_id, name, type, value_str) VALUES (1, 'lang', 0, 'fr')
  ON DUPLICATE KEY UPDATE value_str='fr';

另外,正如大多数人所说,序列化和存储首选项并不是一个特别好的主意,因为:

  1. 你不能用查询检索单个值,你必须检索整个序列化字符串,反序列化它,并丢弃不必要的数据。
  2. 它很容易损坏,而且很难恢复。
  3. 编写一个原始查询是一件痛苦的事情,例如:全局修复某个设置。
  4. 你将本质上是表格数据存储在单个表字段中。

2016年9月回顾编辑:

在此期间,我与人们就如何最好地存储可选设置以及上面定义的一般表结构进行了一些争论。

虽然这个表结构不是完全,但也不是完全。它试图在糟糕的情况下做到最好。只要您能够适应这些设置,可选设置的序列化就可以工作:

  1. 所有货物一次装载,没有挑选和选择。
  2. 不可索引、不可搜索、不可修改

那么你可以考虑在Users表中添加一个像optional_settings这样的字段,其中包含序列化的[例如:JSON]形式的设置。您确实需要权衡上述内容,但这是一种更直接的方法,并且可以存储更复杂的设置。

同样,如果你使用像TEXT这样的LOB类型来存储数据,那么至少在MySQL中,数据不一定存储在"行"中。

无论如何,由决定应用程序的需求和约束是什么,并根据该信息做出最佳选择。

这完全取决于数据库的设置和模式。无论你做什么,我都会建议不要按照你的建议1来序列化数据,如果你序列化了数据,你就不能再对它写查询了,你需要使用你序列化它的语言来反序列化它(或者用那种语言写一些类似的东西)。

我推荐的选项是将设置放在users表中,每列1个设置。这样做的缺点是,当向应用程序添加新设置时,必须编写一些DDL脚本来添加新列。这样做的一个(非常好的)好处是,每个设置都可以有自己的数据类型。如果这个设置是可选的,也会有存储损失。

另一个选项可以使用设置表,如您所建议的,主键为(user_id, setting_name),第三列为设置值。此解决方案假定所有设置都具有相同的数据类型。您不需要编写DDL脚本来添加新的设置,只需使用新的键名即可。

总是同样的问题:你多久需要更改这些数据?在我看来,有一个单独的表总是一个很好的解决方案,因为它分离了应用程序的不同方面。

有一个preferences列,这不是一个好主意,IMHO,因为每当你的用户改变它的设置,你将不得不序列化他所有的数据存储在users表,无论它只是一个单独的update。如果您真的想将所有内容存储在users中,则应该将设置分成不同的列。

第二个选项,但修改为单独存储设置。不要在字段中存储序列化的数据,因为在这种情况下,这是不好的做法。

想想这个:你有这样的,你在那里存储用户的国家,或者如果它是注册到你的时事通讯。后来……你需要知道有多少人来自俄罗斯。你是怎么做的?一个接一个地解码,然后增加一个计数器?(或使用您的第二种方法,只是运行一个简单的SELECT COUNT(id)查询?)

我将与设置表,因为它将使它更容易访问以后。当您尝试在单列中创建名称值对等操作时,稍后尝试进行设计查询以访问数据时可能会遇到问题。

这可能不适合您当前的情况,但NoSQL数据库(如Mongo)非常适合此操作。例如,这是一个mongo数据库,每个用户对象实际上可以有不同的属性,你仍然可以在它们上面搜索。

也就是说,对于您所处的情况,在过去,我遵循这里的其他答案的建议,并有一个单独的表。有两种方法可以做到这一点:有一个单独的表,您更愿意修改其中的列,并对它进行连接。或者,一个更简单的解决方案,使用一个单独的表,如

用户、参数、值。

那么每个用户可以有不同的额外值。

最好的方法取决于你需要的性能等等