Shu*_*hya 184 mysql sql database sql-server optimization
我正在实现以下用于在我的表中存储用户相关数据的模型 - 我有2列 - uid(主键)和一个meta以JSON格式存储有关用户的其他数据的列.
uid | meta
--------------------------------------------------
1 | {name:['foo'],
| emailid:['foo@bar.com','bar@foo.com']}
--------------------------------------------------
2 | {name:['sann'],
| emailid:['sann@bar.com','sann@foo.com']}
--------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
这是一个更好的方式(性能明智的,设计明智)比一列,每个属性模型,其中表将不得不像许多列uid,name,emailid.
我喜欢第一个模型,你可以添加尽可能多的字段,没有限制.
此外,我想知道,现在我已经实现了第一个模型.如何对其执行查询,例如,我想获取所有名称为'foo'的用户?
问题 - 在数据库中使用-JSON或每个字段的列存储用户相关数据(请记住数字不固定)的更好方法是什么?另外,如果实现了第一个模型,如何查询数据库如上所述?我是否应该同时使用这两个模型,将查询可能搜索的所有数据存储在一个单独的行中,将其他数据存储在JSON中(是不同的行)?
由于我需要执行搜索的列数不会太多,因此使用这两个模型是否明智?我需要搜索的数据的每列密钥和其他人的JSON(在同一个MySQL数据库中)?
Col*_*n M 180
鉴于这个问题/答案已经获得了一些人气,我认为值得更新.
当这个问题最初发布时,MySQL不支持JSON数据类型,并且PostgreSQL中的支持还处于起步阶段.从5.7开始,MySQL 现在支持JSON数据类型(以二进制存储格式),PostgreSQL JSONB已经成熟.这两种产品都提供了可以存储任意文档的高性能JSON类型,包括支持索引JSON对象的特定键.
但是,我仍然支持我的原始声明,即在使用关系数据库时,您的默认首选项应该仍然是每列值列.关系数据库仍然建立在假设其中的数据将被很好地规范化的基础上.查看计划程序在查看列时比在查看JSON文档中的键时具有更好的优化信息.可以在列之间创建外键(但不能在JSON文档中的键之间创建).重要的是:如果您的架构的大多数都足够易变以证明使用JSON,那么您可能至少要考虑关系数据库是否是正确的选择.
也就是说,很少有应用程序是完美的关系或文档导向.大多数应用程序都有两种组合.以下是我个人在关系数据库中发现JSON有用的一些示例:
存储联系人的电子邮件地址和电话号码时,将其作为值存储在JSON数组中比管理多个单独的表更容易
保存任意键/值用户首选项(其中值可以是布尔值,文本或数字,并且您不希望为不同的数据类型分别具有列)
存储没有定义架构的配置数据(如果您正在构建Zapier或IFTTT并且需要为每个集成存储配置数据)
我相信还有其他人,但这些只是一些简单的例子.
如果您真的希望能够无限制地添加任意数量的字段(除了任意文档大小限制),请考虑使用NoSQL解决方案,例如MongoDB.
对于关系数据库:每个值使用一列.将JSON blob放在列中使得查询几乎不可能(当您实际找到有效的查询时,会非常慢).
关系数据库在索引时利用数据类型,并且旨在使用规范化结构实现.
作为旁注:这并不是说你永远不应该将JSON存储在关系数据库中.如果您要添加真正的元数据,或者您的JSON描述的信息不需要查询且仅用于显示,那么为所有数据点创建单独的列可能会过度.
Hom*_*man 58
像大多数事情"它取决于".将数据存储在列或JSON中本身并不正确或错误/好或坏.这取决于您以后需要做什么.您预测的访问此数据的方式是什么?你需要交叉引用其他数据吗?
其他人已经很好地回答了技术上的权衡.
没有多少人讨论过您的应用和功能随着时间的推移而发展,以及这种数据存储决策如何影响您的团队.
因为使用JSON的诱惑之一是避免迁移模式,因此如果团队没有规范,那么将另一个键/值对粘贴到JSON字段中非常容易.它没有迁移,没有人记得它是什么.没有验证.
我的团队在postgres的传统专栏中使用了JSON,起初它是切片面包以来最好的东西.JSON很有吸引力,也很强大,直到有一天我们意识到灵活性是有代价的,而且它突然变成了一个真正的痛点.有时这一点很快就会迅速增加,然后很难改变,因为我们在这个设计决策之上已经建立了很多其他的东西.
加班,添加新功能,使用JSON中的数据导致查询比查看传统列时可能添加的查询更复杂.因此,我们开始将某些键值捕获回列中,以便我们可以进行连接并在值之间进行比较.馊主意.现在我们有重复.一个新的开发人员会加入并混淆?我应该挽回的价值是多少?JSON one还是列?
JSON字段变成了垃圾抽屉,用于这个和那个小部分.没有数据库级别的数据验证,文档之间没有一致性或完整性.这将所有责任推到了应用程序中,而不是从传统列中获取硬类型和约束检查.
回顾过去,JSON允许我们快速迭代并获得一些东西.太棒了.然而,在我们达到某个团队规模之后,它的灵活性也使我们能够忍受长期的技术债务,从而减缓后续功能演变的进程.谨慎使用.
仔细思考数据的性质是什么.这是您的应用程序的基础.如何随着时间的推移使用数据.它怎么可能改变?
Ada*_*dam 27
只是折腾它,但WordPress有这种东西的结构(至少WordPress是我观察它的第一个地方,它可能起源于其他地方).
它允许无限密钥,并且比使用JSON blob更快搜索,但不如某些NoSQL解决方案快.
uid | meta_key | meta_val
----------------------------------
1 name Frank
1 age 12
2 name Jeremiah
3 fav_food pizza
.................
Run Code Online (Sandbox Code Playgroud)
编辑
用于存储历史/多个键
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
.................
Run Code Online (Sandbox Code Playgroud)
并通过以下方式查询:
select meta_val from `table` where meta_key = 'name' and uid = 1 order by meta_id desc
Run Code Online (Sandbox Code Playgroud)
Nic*_*los 13
这种方法的缺点正是你提到的:
因为每次你需要对它进行文本搜索时,它会使搜索速度非常慢.
而是每列的值匹配整个字符串.
您的方法(基于JSON的数据)适用于您不需要搜索的数据,只需要与您的常规数据一起显示.
编辑:只是为了澄清,上面是经典的关系数据库.NoSQL在内部使用JSON,如果这是期望的行为,则可能是更好的选择.
基本上,您使用的第一个模型称为基于文档的存储.您应该看看流行的NoSQL基于文档的数据库,如MongoDB和CouchDB.基本上,在基于文档的数据库中,您将数据存储在json文件中,然后您可以查询这些json文件.
第二个模型是流行的关系数据库结构.
如果你想使用像MySql这样的关系数据库,那么我建议你只使用第二个模型.使用MySql和存储数据没有意义,就像在第一个模型中一样.
要回答第二个问题,如果您使用第一个模型,则无法像'foo'那样查询名称.
看来您主要是在犹豫是否使用关系模型。
就目前而言,您的示例相当适合关系模型,但是当您需要使此模型发展时,问题当然可能会出现。
如果您的主要实体(用户)只有一个(或几个预先确定的)属性级别,您仍然可以在关系数据库中使用实体属性值 (EAV) 模型。(这也有利有弊。)
如果您预计使用应用程序搜索的结构化值较少,那么 MySQL 可能不是这里的最佳选择。
如果您使用的是 PostgreSQL,您可能会两全其美。(这真的取决于这里数据的实际结构...... MySQL 也不一定是错误的选择,NoSQL 选项可能很有趣,我只是建议替代方案。)
事实上,PostgreSQL 可以在(不可变的)函数上建立索引(据我所知 MySQL 不能),在最近的版本中,你可以直接在 JSON 数据上使用 PLV8 来在感兴趣的特定 JSON 元素上建立索引,这将改进搜索该数据时的查询速度。
编辑:
由于我需要执行搜索的列不会太多,因此使用这两种模型是否明智?我需要搜索的数据的每列键和其他人的 JSON(在同一个 MySQL 数据库中)?
混合两个模型不一定是错误的(假设额外的空间可以忽略不计),但如果您不确保两个数据集保持同步,则可能会导致问题:您的应用程序绝不能在不更新另一个的情况下更改其中一个.
实现此目的的一个好方法是让触发器执行自动更新,方法是在进行更新或插入时在数据库服务器中运行存储过程。据我所知,MySQL 存储过程语言可能不支持任何类型的 JSON 处理。再次支持 PLV8 的 PostgreSQL(可能还有其他具有更灵活存储过程语言的 RDBMS)应该更有用(使用触发器自动更新关系列与以相同方式更新索引非常相似)。
| 归档时间: |
|
| 查看次数: |
128434 次 |
| 最近记录: |