在数据库中存储JSON与为每个密钥创建一个新列

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

 uid   | meta
--------------------------------------------------
 1     | {name:['foo'], 
       |  emailid:['foo@bar.com','bar@foo.com']}
--------------------------------------------------
 2     | {name:['sann'], 
       |  emailid:['sann@bar.com','sann@foo.com']}
--------------------------------------------------

这是一种更好的方式(性能明智,设计明智)比每列属性模式,其中表中将有许多列像uidnameemailid

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

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

问题 - 在数据库中使用-JSON或者每场都存储用户相关数据的更好方法(记住数量不固定的字段)? 另外,如果实施第一个模型,如何按上述方式查询数据库? 我是否应该使用这两种模型,将所有可能由查询搜索的数据存储在单独的行中,并将其他数据存储在JSON中(是不同的行)?


更新

由于我不需要执行搜索的列太多,因此使用这两种模型是否明智? 我需要搜索的数据的按键列和其他人的JSON(在同一个MySQL数据库中)?


2017年6月4日更新

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

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

但是,我仍然坚持我原来的声明,即在使用关系数据库时,您的默认首选项仍应为每列值。 关系数据库仍然建立在假设它们内部的数据将被很好地标准化的基础上。 在查看列时,查询规划器比查看JSON文档中的键时具有更好的优化信息。 可以在列之间创建外键(但不能在JSON文档中的键之间)。 重要的是:如果大部分模式足够易于使用JSON,那么您可能至少要考虑关系数据库是否是正确的选择。

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

  • 存储联系人的电子邮件地址和电话号码时,将它们作为JSON数组中的值进行存储比将多个单独的表格更容易管理

  • 保存任意键/值用户首选项(值可以是布尔值,文本值或数字值,并且不希望为不同的数据类型分开列)

  • 存储没有定义模式的配置数据(如果您正在构建Zapier或IFTTT并需要为每个集成存储配置数据)

  • 我确定也有其他人,但这些只是一些简单的例子。

    原始答复

    如果您真的希望能够根据需要添加任意数量的字段(除了任意文档大小限制之外),请考虑使用NoSQL解决方案(例如MongoDB)。

    对于关系数据库:每个值使用一列。 将JSON blob放入列中几乎不可能进行查询(并且在您实际查找可用的查询时非常缓慢)。

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

    作为一个方面说明:这并不是说你不应该将JSON存储在关系数据库中。 如果您要添加真实的元数据,或者如果您的JSON描述的信息不需要查询并且仅用于显示,那么为所有数据点创建一个单独的列可能是矫枉过正的。


    像大多数事情“取决于”。 在数据列或JSON中存储数据本身并不是对或错/好或坏。 这取决于你以后需要做什么。 你预计访问这些数据的方式是什么? 你需要交叉引用其他数据吗?

    其他人已经很好地回答了技术权衡的问题。

    没有多少人讨论过您的应用和功能会随着时间的推移而发生变化,以及此数据存储决策如何影响您的团队。

    因为使用JSON的诱惑之一是为了避免迁移模式,所以如果团队没有遵守规则,那么将另一个键/值对插入JSON字段非常容易。 没有任何迁移,没有人记得它的用途。 没有验证。

    我的团队在postgres的侧面传统栏目中使用了JSON,起初它是自切片面包以来最好的。 JSON很吸引人,而且功能强大,直到有一天我们意识到灵活性是以牺牲成本为代价的,这突然成为一个真正的痛点。 有时候,这一点非常迅速地升高,然后变得很难改变,因为我们在这个设计决策的基础上构建了很多其他的东西。

    加班时,添加新功能,使用JSON中的数据导致查询查询比查看传统列时可能添加的查询更复杂。 因此,我们开始将某些关键值捕获到列中,以便我们可以进行连接并对值进行比较。 馊主意。 现在我们有重复。 一个新的开发者会加入并且感到困惑? 我应该挽回的价值是什么? JSON一个还是列?

    JSON字段成为这个和那个小部分的垃圾抽屉。 数据库级没有数据验证,文档之间没有一致性或完整性。 这将所有责任推到了应用程序中,而不是从传统列中获取硬性类型和约束检查。

    回顾一下,JSON使我们能够快速迭代并获得一些东西。 太好了。 然而,在我们达到一定团队规模后,它的灵活性也使我们能够用一长串技术债务来悬挂自己,然后放慢后续特征演进的进程。 谨慎使用。

    仔细考虑你的数据的性质。 这是你的应用程序的基础。 随着时间的推移数据将如何使用。 它怎么可能改变?


    把它扔到那里,但是WordPress有这样的结构(至少WordPress是我观察到的第一个地方,它可能起源于其他地方)。

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

    uid   |   meta_key    |   meta_val
    ----------------------------------
    1         name            Frank
    1         age             12
    2         name            Jeremiah
    3         fav_food        pizza
    .................
    

    编辑

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

    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
    .................
    

    并通过这样的查询:

    select meta_val from `table` where meta_key = 'name' and uid = 1 order by meta_id desc
    
    链接地址: http://www.djcxy.com/p/68633.html

    上一篇: Storing JSON in database vs. having a new column for each key

    下一篇: How to delete a column from a table in MySQL