在MySQL中存储“额外”用户数据的最佳方法是什么?

6
我正在为我的CMS的用户模块添加一个新功能,但遇到了难题...或者说,遇到了岔路口,我想在做出决定之前从stackoverflow上获得一些意见。
基本上,我想允许管理员添加新的“额外”用户字段,用户可以在注册时填写、在个人资料中编辑和/或由其他模块控制。其中一个例子是生日字段、自我介绍或者用户在网站上获得的积分。不用说,存储的数据将是各种各样的,范围从大量文本到小整数值不等。更糟糕的是 - 我希望有搜索此数据的选项。
那么,最好的方法是什么呢?现在,我倾向于拥有以下列的表。
userid, refFieldID, varchar, tinyint, smallint, int, text, date, datetime, etc.

我更喜欢第一种方法,因为这将使搜索速度显着更快,并且引用表(包含所有字段数据的表,例如字段名称、是否可搜索等)可以引用存储该字段数据时应使用的列。

另一个想法是,有人向我建议并在其他解决方案中看到过(例如vBulletin,尽管我已经看到其他一些名字我暂时想不起来的解决方案),其中只有userid、参考id和medtext字段。我对MySQL了解得不够深入,无法确定这种方法是否会更慢,可能会有更大的开销。

那么哪种方法最好呢?还有其他我没有考虑到的方法吗?无论我最终使用哪种方法,它都需要快速搜索,不会占用太多空间(稍微有点开销也没关系),最好允许对数据进行复杂查询。

2个回答

3
我认为键值表可能是最好的解决方案。我的第一反应是只存储文本列,就像vBulletin一样。但是,如果您想要添加数据存储的可扩展性和搜索能力,就像您所描述的那样,我建议:
  • 1个中/长文本或中/长二进制字段,用于任意文本/二进制存储(存储的内容+3-4个字节的开销)。选择中等长度而不是长长度的唯一原因是将存储限制为2^24字节(16.7 MB)与2^32字节(2 GB)相比。
  • 1个整数(4个字节)或bigint(8个字节)
  • 1个日期时间(8个字节)
  • 也许1个浮点数或双精度浮点数(4-8个字节)用于浮点数存储
这些字段将允许您在表中存储几乎任何类型的数据,但不会膨胀表的宽度**(像varchar一样),避免任何冗余存储(例如tinyint和mediumint等)。存储在longtext字段中的文本仍然可以使用全文索引或常规有限长度索引进行合理的搜索(例如index longtext_storage(8))。
** 所有blob值(如longtext)都独立于主表存储。

哇,谢谢,我实际上打算回复第一个同意#1选择哪些列的人-但我想我不必了:)。关于您的帖子-您是指文本和blob,int和bigint吗?还是其中之一?另外,您对添加一个'bool'(tinyint(1))列有何感想?我可以看到它非常有用,可能会频繁使用-在您的意见中,这值得节省3个字节吗?此外,列数是否会增加行在磁盘上的大小?当然是空列。我不怀疑您(令人惊叹的)表格布局,只是好奇。 - Jon
对于我的列表中的每个项目,需要3或4列,具体取决于是否需要浮点支持。至于tinyint(1)-将其存储在整数列中即可。通过添加tinyint(1),您浪费了一个字节,而不是节省了3个字节。在MySQL中,表中的每一行始终具有相同的宽度 - 在大多数其他RDBMS中也是如此。(varchar如何影响这一点有点复杂)。“宽度”也称为“行大小”。 - wuputah

0

一个可能适用于您的技术是将这些任意数据存储为文本,使用JSON、XML或YAML等符号表示法。这个决定取决于您需要如何访问数据:如果您只查找每个用户的完整用户数据块,那么这可能是理想的。如果您需要在用户数据的特定字段上运行SQL查询,则需要使用纯SQL或混合方法。

许多新型的高度可扩展的“NoSQL”系统似乎更喜欢JSON数据(例如MongoDB、CouchDB和Project Voldemort)。它很简洁,您可以创建包括映射(JSON对象)和列表(JSON数组)在内的任意复杂结构。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接