首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将JSON存储在数据库中,而每个键都有一个新列

将JSON存储在数据库中,而每个键都有一个新列
EN

Stack Overflow用户
提问于 2013-03-13 01:11:49
回答 10查看 185.3K关注 0票数 260

我正在实现以下模型来在我的表中存储与用户相关的数据-我有两列- uid (主键)和一个meta列,它以JSON格式存储有关用户的其他数据。

代码语言:javascript
复制
 uid   | meta
--------------------------------------------------
 1     | {name:['foo'], 
       |  emailid:['foo@bar.com','bar@foo.com']}
--------------------------------------------------
 2     | {name:['sann'], 
       |  emailid:['sann@bar.com','sann@foo.com']}
--------------------------------------------------

这是一种比每个属性一列模型更好的方法(在性能方面,在设计方面),在这种模式下,表将有许多列,如uidnameemailid

我喜欢第一个模型的原因是,你可以添加尽可能多的字段,没有限制。

另外,我想知道,既然我已经实现了第一个模型。我如何对其执行查询,例如,我想获取所有名称为'foo‘的用户?

field-在数据库中使用- JSON或按字段列存储与用户相关的数据(请记住字段的数量不固定),哪种方法更好?另外,如果实现了第一个模型,如何按照上述方式查询数据库?我是否应该同时使用这两个模型,将查询可以搜索的所有数据存储在单独的行中,而将其他数据存储在JSON中(是不同的行)?

更新

既然不会有太多的列需要执行搜索,那么同时使用这两个模型是否明智?我需要搜索的数据是每列一个键,而其他数据是JSON (在同一个MySQL数据库中)?

EN

回答 10

Stack Overflow用户

发布于 2013-03-13 01:15:18

更新2017年6月4日

鉴于这个问题/答案已经获得了一些人气,我认为它值得更新。

当这个问题最初发布时,MySQL还不支持JSON数据类型,而PostgreSQL对它的支持还处于起步阶段。从5.7开始,MySQL now supports a JSON data type (以二进制存储格式)和PostgreSQL JSONB已经明显成熟。这两种产品都提供了可以存储任意文档的高性能JSON类型,包括对JSON对象的特定键进行索引的支持。

但是,我仍然坚持我最初的声明,即在使用关系数据库时,您的默认首选项应该仍然是按值列。关系数据库仍然建立在这样的假设之上,即其中的数据将被相当好地规范化。与查看JSON文档中的键相比,查询规划器在查看列时具有更好的优化信息。外键可以在列之间创建(但不能在JSON文档中的键之间创建)。重要的是:如果您的大多数模式都不稳定到足以证明使用JSON的程度,那么您可能至少需要考虑一下关系数据库是否是正确的选择。

也就是说,很少有应用程序是完全面向关系或面向文档的。大多数应用程序都混合了这两种方法。以下是我个人发现JSON在关系数据库中很有用的一些示例:

  • 存储联系人的电子邮件地址和电话号码时,将它们作为值存储在JSON数组中要比管理多个单独的表容易得多
  • 保存任意键/值用户首选项(其中的值可以是布尔值、文本或数字,并且您不希望为不同的数据类型有单独的列)
  • 存储没有定义模式的配置数据(如果您正在构建Zapier或IFTTT,并且需要为每个集成存储配置数据)

我相信还有其他的,但这些只是几个简单的例子。

原始答案

如果您确实希望能够不受限制地添加任意数量的字段(除了任意的文档大小限制之外),可以考虑使用MongoDB这样的NoSQL解决方案。

对于关系数据库:每个值使用一列。将JSON blob放在一个列中会使查询变得几乎不可能(当您实际找到一个可以工作的查询时,速度会慢得令人痛苦)。

关系数据库在索引时利用数据类型,并打算使用规范化结构来实现。

附注:这并不是说您永远不应该将JSON存储在关系数据库中。如果您正在添加真正的元数据,或者如果您的JSON描述的是不需要查询且仅用于显示的信息,那么为所有数据点创建单独的列可能过于夸张了。

票数 235
EN

Stack Overflow用户

发布于 2016-02-11 00:08:10

就像大多数事情一样,“视情况而定”。将数据存储在列或JSON中本身并不是对或错/好或坏。这取决于您稍后需要如何处理它。您预测的访问此数据的方式是什么?您是否需要交叉引用其他数据?

其他人已经很好地回答了什么是技术上的权衡。

没有多少人讨论过你的应用程序和功能随着时间的推移而发展,以及这一数据存储决策如何影响你的团队。

因为使用JSON的诱惑之一是避免迁移模式,因此如果团队不守纪律,很容易将另一个键/值对插入到JSON字段中。它没有迁移,没有人记得它是用来做什么的。上面没有验证。

我的团队在postgres中使用了JSON和传统的列,一开始这是自切片面包以来最好的东西。JSON很有吸引力和强大,直到有一天我们意识到灵活性是有代价的,这突然成了一个真正的痛点。有时候,这一点很快就会出现,然后就很难改变了,因为我们已经在这个设计决策的基础上构建了很多其他的东西。

加班加点,添加新功能,将数据放在JSON中会导致比我们坚持使用传统列所添加的查询更复杂的查询。因此,我们开始将某些键值放回列中,以便我们可以进行连接并在值之间进行比较。馊主意。现在我们有了副本。新的开发人员会加入进来并感到困惑吗?我应该存回的值是什么?JSON one还是column?

JSON字段成了一个垃圾抽屉,里面放着一些零碎的东西。没有数据库级别的数据验证,文档之间没有一致性或完整性。这将所有的责任都推到了应用程序中,而不是从传统的列中获取硬类型和约束检查。

回过头来看,JSON让我们可以非常快速地迭代,并得到一些东西。真是太棒了。然而,当我们达到一定的团队规模后,它的灵活性也允许我们用一长串技术债务来拖累自己,这就减慢了随后的功能演化进程。请谨慎使用。

仔细考虑你的数据的性质。它是你的应用程序的基础。随着时间的推移,数据将如何使用。它可能会发生怎样的变化?

票数 87
EN

Stack Overflow用户

发布于 2013-03-13 01:49:06

简单地说,WordPress对这类东西有一个结构(至少WordPress是我观察到它的第一个地方,它可能起源于其他地方)。

它允许无限的键,并且搜索速度比使用JSON blob快,但不如一些NoSQL解决方案快。

代码语言:javascript
复制
uid   |   meta_key    |   meta_val
----------------------------------
1         name            Frank
1         age             12
2         name            Jeremiah
3         fav_food        pizza
.................

编辑

用于存储历史记录/多个密钥

代码语言:javascript
复制
uid   | meta_id    |   meta_key    |   meta_val
----------------------------------------------------
1        1             name            Frank
1        2             name            John
1        3             age             12
2        4             name            Jeremiah
3        5             fav_food        pizza
.................

并通过类似如下的方式进行查询:

代码语言:javascript
复制
select meta_val from `table` where meta_key = 'name' and uid = 1 order by meta_id desc
票数 30
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15367696

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档