我正在实现以下模型存储用户相关的数据在我的表-我有2列- uid(主键)和一个元列,其中存储关于JSON格式的用户的其他数据。
uid | meta
--------------------------------------------------
1 | {name:['foo'],
| emailid:['foo@bar.com','bar@foo.com']}
--------------------------------------------------
2 | {name:['sann'],
| emailid:['sann@bar.com','sann@foo.com']}
--------------------------------------------------
这种方法(在性能和设计方面)是否比每个属性一列模型更好?在每个属性一列模型中,表将有许多列,如uid、name、emailid。
我喜欢第一个模型的地方是,你可以添加尽可能多的字段,没有限制。
另外,我想知道,既然我已经实现了第一个模型。我如何对它执行查询,比如,我想获取所有名称为'foo'的用户?
问:在数据库中存储用户相关数据(请记住,字段的数量是不固定的),使用JSON还是每个字段列?另外,如果实现了第一个模型,如何查询上述数据库?我应该使用这两个模型,通过存储所有的数据,可以在一个单独的行和JSON(是不同的行)的数据查询搜索?
更新
由于没有太多需要执行搜索的列,使用这两种模型是否明智?每列键的数据,我需要搜索和JSON为其他人(在同一个MySQL数据库)?
2017年6月4日更新
鉴于这个问题/答案已经获得了一些欢迎,我认为它值得更新。
当这个问题最初发布时,MySQL还不支持JSON数据类型,而PostgreSQL的支持还处于起步阶段。从5.7开始,MySQL现在支持JSON数据类型(二进制存储格式),而PostgreSQL JSONB已经显著成熟。这两个产品都提供了可以存储任意文档的高性能JSON类型,包括支持索引JSON对象的特定键。
However, I still stand by my original statement that your default preference, when using a relational database, should still be column-per-value. Relational databases are still built on the assumption of that the data within them will be fairly well normalized. The query planner has better optimization information when looking at columns than when looking at keys in a JSON document. Foreign keys can be created between columns (but not between keys in JSON documents). Importantly: if the majority of your schema is volatile enough to justify using JSON, you might want to at least consider if a relational database is the right choice.
也就是说,很少有应用程序是完全关系的或面向文档的。大多数应用程序都是两者的混合。以下是我个人认为JSON在关系数据库中很有用的一些例子:
在存储联系人的电子邮件地址和电话号码时,将它们存储为JSON数组中的值要比管理多个单独的表容易得多
保存任意键/值用户首选项(其中值可以是布尔值、文本值或数字值,并且您不希望为不同的数据类型设置单独的列)
存储没有定义模式的配置数据(如果您正在构建Zapier或IFTTT,并且需要为每个集成存储配置数据)
我相信还有其他的例子,但这只是几个简单的例子。
原来的答案
如果您真的希望能够添加任意数量的字段,而不受任何限制(除了任意文档大小限制之外),可以考虑使用NoSQL解决方案,例如MongoDB。
对于关系数据库:每个值使用一列。将JSON blob放在列中几乎不可能进行查询(并且当您真正找到一个有效的查询时,会非常缓慢)。
关系数据库在建立索引时利用了数据类型的优势,并打算用规范化的结构来实现。
顺便说一句:这并不是说永远不应该在关系数据库中存储JSON。如果要添加真正的元数据,或者JSON描述的信息不需要查询,只用于显示,那么为所有数据点创建一个单独的列可能有些过分。
和大多数事情一样,“视情况而定”。将数据存储在列或JSON中本身没有对错/好坏之分。这取决于你以后要用它做什么。您预计使用什么方式访问这些数据?您是否需要交叉引用其他数据?
其他人已经很好地回答了技术权衡是什么。
没有多少人讨论过你的应用程序和功能会随着时间的推移而发展,以及这个数据存储决策如何影响你的团队。
因为使用JSON的诱惑之一是避免迁移模式,所以如果团队没有纪律,很容易在JSON字段中插入另一个键/值对。它不需要迁移,没有人记得它是干什么用的。它没有验证。
我的团队在postgres中使用JSON和传统列一起使用,起初这是自切片面包以来最好的东西。JSON是有吸引力和强大的,直到有一天我们意识到灵活性是有代价的,它突然成为一个真正的痛点。有时,这个点很快就会上升,然后就很难改变了,因为我们已经在这个设计决策的基础上构建了太多其他东西。
随着时间的推移,添加新功能,使用JSON格式的数据会导致看起来比使用传统列所添加的查询更复杂。然后我们开始把某些键值捞出来放到列中,这样我们就可以在值之间进行连接和比较。坏主意。现在我们有了复制。一个新的开发人员会感到困惑吗?我应该存回哪个值呢?JSON还是列?
JSON字段变成了存放这个和那个小碎片的垃圾抽屉。没有数据库级别的数据验证,文档之间没有一致性或完整性。这将所有的责任推到应用程序中,而不是从传统的列中获得严格的类型和约束检查。
回顾过去,JSON让我们能够快速迭代并创造出一些内容。太棒了。然而,当我们达到一定的团队规模后,它的灵活性也让我们陷入了技术债务的长绳中,从而减缓了随后的功能开发进程。请谨慎使用。
仔细思考你的数据的性质是什么。这是你的应用程序的基础。随着时间的推移,数据将如何使用。它可能会发生怎样的变化?
似乎您主要在犹豫是否要使用关系模型。
就目前的情况而言,您的示例相当适合关系模型,但是当您需要使该模型演进时,问题当然会出现。
如果您的主实体(用户)只有一个(或几个预先确定的)属性级别,您仍然可以在关系数据库中使用实体属性值(entity Attribute Value, EAV)模型。(这也有利弊。)
如果您希望使用应用程序搜索的结构化值较少,那么MySQL可能不是最佳选择。
如果你在使用PostgreSQL,你可能会两全其美。(这真的取决于这里数据的实际结构……MySQL也不一定是错误的选择,NoSQL选项可能是有趣的,我只是建议替代方案。)
事实上,PostgreSQL可以在(不可变的)函数上建立索引(据我所知,MySQL不能),在最近的版本中,你可以直接在JSON数据上使用PLV8来在特定的JSON元素上建立索引,这将提高你搜索数据时的查询速度。
编辑:
因为不会有太多的列需要执行
搜索,使用这两个模型明智吗?数据的每列键
我需要搜索和JSON为其他人(在同一个MySQL数据库)?
混合使用两个模型不一定是错误的(假设额外的空间可以忽略不计),但是如果不能确保两个数据集保持同步,则可能会导致问题:应用程序必须在不更新另一个数据集的情况下更改其中一个。
A good way to achieve this would be to have a trigger perform the automatic update, by running a stored procedure within the database server whenever an update or insert is made. As far as I'm aware, the MySQL stored procedure language probably lack support for any sort of JSON processing. Again PostgreSQL with PLV8 support (and possibly other RDBMS with more flexible stored procedure languages) should be more useful (updating your relational column automatically using a trigger is quite similar to updating an index in the same way).