在MySQL字段中存储CSV - 是个坏主意吗?

3
我有两个表,一个用户表和一个物品表。在用户表中,有一个字段“items”。“items”表只包含唯一的id和item_name。
现在每个用户可以拥有多个物品。我想避免创建第三个表来连接用户和物品,而是在user_table中有一个字段,将与用户相关联的项ids存储在一个“csv”字段中。
因此,任何给定的用户都将具有一个“items”字段,它可以具有像“32,3,98,56”这样的值。
也许值得提到的是,每个用户的最大物品数量相当有限(<5)。
问题是:与包含用户->项对的第三个表相比,这种方法通常是一个坏主意吗?
当您想要查找用户的所有项目时,第三个表不会创建相当大的开销(我必须逐个迭代MySQL返回的所有元素)。

2
是的,这很糟糕。可用性和性能都受到了严重影响。最好为该信息添加一个额外的表格。 - Linkan
1
非常非常糟糕的想法。永远不要这样做。 - Gurwinder Singh
然而,在这种情况下,我仍然不明白为什么。如果有人能告诉我为什么这是一个如此糟糕的想法,我会非常感激。 - Armin Hierstetter
此外,如果项目数量较少,为什么不添加更多字段呢?这不是一个很好的想法,但绝对比一个有时会被解析为整数列表的不透明字符串字段要好。 - Panagiotis Kanavos
可能是重复问题 [在数据库列中存储分隔列表真的那么糟糕吗?] (https://dev59.com/gHA65IYBdhLWcg3wvxaE) - Don't Panic
显示剩余10条评论
2个回答

2

您不希望以逗号分隔的形式存储值。

考虑一下当您决定将此列与其他表联接时的情况。

假设您有以下内容:

x  items
1  1, 2, 3
1  1, 4
2  1

如果您想为每个 x 查找不同的值,即:

x  items
1  1, 2, 3, 4
2  1

或者您可能想检查它是否包含数字3

或者您可能想将它们转换成单独的行:

x  items
1  1
1  2
1  3
1  1
1  4
2  1

这将是一件非常麻烦的事情。

首先至少要使用规范化第一原则 - 每个值都应该有单独的行。

现在,假设你最初的表格如下:

x  item
1  1
1  2
1  3
1  1
1  4
2  1

您可以轻松地将其转换为CSV值:
select x, group_concat(item order by item) items
from t
group by x

如果您想查找 x = 1 是否有项目 3。很简单。
select * from t where x = 1 and item = 3

在以前的情况下,将使用可怕的find_in_set

select * from t where x = 1 and find_in_set(3, items);

如果你认为可以使用类似于CSV值的方式进行搜索,那么首先,like %x%将无法使用索引。其次,它会产生错误的结果。
比如你想检查项目"ab"是否存在,执行 %ab% 将会返回包含"abc abcd abcde ..."的行。
如果你有许多用户和项目,那么我建议创建三张表:一个带有主键userid的users表,另一个带有主键itemid的items表和最后一个映射表user_item,其中包括userid和itemid列。
如果你知道只需要存储和检索这些值而不进行任何操作(如连接,搜索,去重,拆分成单独的行等),也许只是也许,你可以这样做(但我仍然不建议这样做)。

也许我太蠢了,但我不明白:我的用户表包含的数据比商品表多得多。所以在用户表中,我会有数行属于同一个用户的数据?当我想要检索拥有特定商品的行时,我只需要执行SELECT * from users WHERE items LIKE "%x%" - 就可以了。我就能得到所有拥有这种商品的用户。更重要的是:我仍然不知道如何选择包含所有商品的用户行,当这些商品数据分散在不同的表格里时。抱歉,我并不是很熟悉 Mysql。 - Armin Hierstetter

0

将复杂数据直接存储在关系型数据库中是关系型数据库的非标准用法。通常它们被设计用于规范化数据。

根据软件品牌,有一些扩展可以帮助解决这个问题。或者您可以将CSV文件规范化为适当设计的表格。这取决于很多因素。在这种情况下,请与企业数据架构师交谈。

是否是一个坏主意取决于您的业务需求。我无法从互联网上远程评估您的业务需求。在这种情况下,请与产品经理交谈。


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