将数据作为JSON存储在MySQL中

我认为这是一件可以做的事情。 所以,我从来没有这样做过。 然后,我看到FriendFeed做到了这一点,实际上使他们的数据库规模更好,并减less了延迟。 我很好奇,如果我应该这样做。 而且,如果是这样,那么正确的做法是什么?

基本上,学习如何将所有东西都存储在MySQL中作为CouchDBtypes的数据库是一个很好的地方? 像JSON一样存储所有东西似乎会更容易和更快(不build立,更less的延迟)。

另外,在数据库上存储为JSON的东西是否容易编辑,删除等?

CouchDB和MySQL是两个非常不同的野兽。 JSON是将东西存储在CouchDB中的本地方式。 在MySQL中,最好的办法是将JSON数据作为文本存储在单个字段中。 这完全违背了将其存储在RDBMS中的目的,并且会使每个数据库事务复杂化。

别。

话虽如此,FriendFeed似乎在MySQL之上使用了一个非常自定义的模式 。 这实际上取决于你想要存储什么,关于如何滥用数据库系统几乎没有一个明确的答案,所以对你来说是有意义的。 鉴于这篇文章非常陈旧,而且他们对Mongo和Couch的主要原因还不是很成熟,所以如果MySQL没有为你裁剪,我会重新评估这两个。 现在应该已经成长了很多。

每个人的评论似乎都是从错误的angular度出现的,在关系数据库中通过PHP存储JSON代码是很好的,事实上加载和显示这样的复杂数据会更快,但是您会有devise注意事项,如search,索引等

这样做的最好方法是使用混合数据,例如,如果您需要基于date时间进行search,MySQL(性能调优)将比PHP快得多,而且像search场所的距离等等,MySQL也应该是很多的更快(通知search不访问)。 您不需要search的数据可以存储在JSON,BLOB或您认为必要的任何其他格式中。

您需要访问的数据非常容易存储为JSON,例如基本的每个案例的发票系统。 如果您拥有正确的HTML表单结构,那么它们从RDBMS中获益不大,并且可以通过json_encoding($ _ POST ['entires'])存储在JSON中。

我很高兴你很高兴使用MongoDB,我希望它能继续为你服务,但是不要以为MySQL总是不受关注,因为你的应用程序的复杂性增加了,你可能最终需要一个RDBMS一些function和function(即使它只是为了退休归档数据或业务报告)

MySQL 5.7现在支持类似于MongoDB和其他无模式文档数据存储的本地JSON数据types:

JSON支持

从MySQL 5.7.8开始,MySQL支持本机JSONtypes。 JSON值不作为string存储,而是使用内部二进制格式,允许快速读取文档元素。 存储在JSON列中的JSON文档在插入或更新时会自动进行validation,并生成错误的无效文档。 JSON文档在创build时被规范化,可以使用大多数比较运算符比如=,<,<=,>,> =,<>,!=和<=>; 有关支持的运算符的信息以及MySQL在比较JSON值时遵循的优先级和其他规则,请参阅JSON值的比较和sorting。

MySQL 5.7.8还引入了一些用于处理JSON值的函数。 这些function包括这里列出的function:

  1. 创buildJSON值的函数:JSON_ARRAY(),JSON_MERGE()和JSON_OBJECT()。 请参阅第12.16.2节“创buildJSON值的函数”。
  2. searchJSON值的函数:JSON_CONTAINS(),JSON_CONTAINS_PATH(),JSON_EXTRACT(),JSON_KEYS()和JSON_SEARCH()。 请参见第12.16.3节“searchJSON值的函数”。
  3. 修改JSON值的函数:JSON_APPEND(),JSON_ARRAY_APPEND(),JSON_ARRAY_INSERT(),JSON_INSERT(),JSON_QUOTE(),JSON_REMOVE(),JSON_REPLACE(),JSON_SET()和JSON_UNQUOTE()。 请参见第12.16.4节“修改JSON值的函数”。
  4. 提供有关JSON值的信息的函数:JSON_DEPTH(),JSON_LENGTH(),JSON_TYPE()和JSON_VALID()。 请参阅第12.16.5节“返回JSON值属性的函数”。

在MySQL 5.7.9和更高版本中,可以使用column-> path作为JSON_EXTRACT(列,path)的简写。 这可以作为SQL语句中列标识符可以出现的列的别名,包括WHERE,ORDER BY和GROUP BY子句。 这包括SELECT,UPDATE,DELETE,CREATE TABLE和其他SQL语句。 左侧必须是JSON列标识符(而不是别名)。 右侧是一个引用的JSONpathexpression式,该expression式针对作为列值返回的JSON文档进行评估。

有关 – >和JSON_EXTRACT()的更多信息,请参见第12.16.3节“searchJSON值的函数”。 有关MySQL 5.7中JSONpath支持的信息,请参阅search和修改JSON值。 另请参阅二级索引和虚拟生成的列。

更多信息:

https://dev.mysql.com/doc/refman/5.7/en/json.html

JSON字符没有什么特别的时候,它归结为存储,字符如

{}[]'az0-9 ….真的没什么特别的,可以存储为文本。

你会遇到的第一个问题是这个

{profile_id:22,用户名:'Robert',密码:'skhgeeht893htgn34ythg9er'}

存储在数据库中并不是那么简单的更新,除非你有自己的过程,并开发了一个MySQL的jsondecode

 UPDATE users SET JSON(user_data,'username') = 'New User'; 

所以,如果你不能这样做,你将不得不先selectjson,解码它,改变它,更新它,所以理论上你可能花更多的时间去构build一个合适的数据库结构!

我确实使用json来存储数据,但只有元数据,不经常更新的数据,不涉及到用户特定的。例如,如果用户添加一个post,并在该post中,他添加图像生病分析图像,并创build拇指和然后以json格式使用拇指URL。

为了说明使用查询获取JSON数据有多困难,我将分享我为处理这个问题所做的查询。

它不考虑数组或其他对象,只是基本的数据types。 您应该将的4个实例更改为存储JSON的列名称,并将myfield的4个实例更改为您要访问的JSON字段。

 SELECT SUBSTRING( REPLACE(REPLACE(REPLACE(column, '{', ''), '}', ','), '"', ''), LOCATE( CONCAT('myfield', ':'), REPLACE(REPLACE(REPLACE(column, '{', ''), '}', ','), '"', '') ) + CHAR_LENGTH(CONCAT('myfield', ':')), LOCATE( ',', SUBSTRING( REPLACE(REPLACE(REPLACE(column, '{', ''), '}', ','), '"', ''), LOCATE( CONCAT('myfield', ':'), REPLACE(REPLACE(REPLACE(column, '{', ''), '}', ','), '"', '') ) + CHAR_LENGTH(CONCAT('myfield', ':')) ) ) - 1 ) AS myfield FROM mytable WHERE id = '3435' 

这真的取决于你的用例。 如果您存储的信息在报告中绝对没有任何价值,并且不会通过与其他表的JOIN进行查询,那么将数据存储在单个文本字段(编码为JSON)中可能是有意义的。

这可以大大简化您的数据模型。 但是,正如RobertPitt所提到的那样,不要指望能够将这些数据与已经正常化的其他数据结合起来。

我想说的是,考虑这个的唯一两个理由是:

  • 使用标准化的方法性能不够好
  • 你不能很容易地build模你的特别stream畅/灵活/不断变化的数据

我在这里写了一些关于我自己的方法:

您使用NoSQL数据存储时遇到了哪些可伸缩性问题?

(请参阅最佳答案)

即使JSON不够快,所以我们使用了自定义文本格式的方法。 工作/继续为我们工作。

有没有原因,你不使用MongoDB的东西? (可能是MySQL的“必需”;只是好奇)

这是一个古老的问题,但我仍然可以看到这在Google的search结果的顶部,所以我想这个问题提出4年后添加一个新的答案将是有意义的。

首先,在RDBMS中存储JSON有更好的支持。 您可以考虑切换到PostgreSQL(尽pipeMySQL从v5.7.7开始支持JSON)。 除了支持更多的function,PostgreSQL使用与MySQL非常相似的SQL命令。 他们添加的function之一是他们提供JSON数据types,你现在可以查询存储的JSON。 ( 关于这个的一些参考 )如果你没有直接在你的程序中进行查询,例如,在php中使用PDO或者在Laravel中使用雄辩,你只需要在你的服务器上安装PostgreSQL并改变数据库连接设置。 你甚至不需要改变你的代码。

大多数情况下,正如其他答案所build议的那样,直接在RDBMS中将数据存储为JSON不是一个好主意。 虽然有一些例外。 我能想到的一种情况是一个链接条目数量可变的字段。

例如,为了存储博客post的标签,通常你需要有一个博客post表,一个标签表和一个匹配表。 所以,当用户想要编辑post时,你需要显示哪个标签与该post相关,你需要查询3个表格。 如果您的匹配表/标签表很长,这会损害性能。

通过将标签作为JSON存储在博客post表中,相同的动作只需要一个表格search。 用户将能够看到博客文章被更快地编辑,但是如果您想报告哪些post链接到标签,或者可以通过标签进行search,那么这会损害性能。

您也可以尝试去规范化数据库。 通过复制数据并以两种方式存储数据,您都可以从两种方法中受益。 你只需要多一点的时间来存储你的数据和更多的存储空间(与更多的计算能力相比,这是便宜的)

这是一个函数,可以保存/更新列中JSON数组的键和另一个检索JSON值的函数。 这个函数是在假设存储JSON数组的列名是json的情况下创build的 。 它正在使用PDO

保存/更新function

 function save($uid, $key, $val){ global $dbh; // The PDO object $sql = $dbh->prepare("SELECT `json` FROM users WHERE `id`=?"); $sql->execute(array($uid)); $data = $sql->fetch(); $arr = json_decode($data['json'],true); $arr[$key] = $val; // Update the value $sql=$dbh->prepare("UPDATE `users` SET `json`=? WHERE `id`=?"); $sql->execute(array( json_encode($arr), $uid )); } 

其中$ uid是用户的ID, $ key – 要更新的JSON键,它的值被提及为$ val

获得价值function

 function get($uid, $key){ global $dbh; $sql = $dbh->prepare("SELECT `json` FROM `users` WHERE `id`=?"); $sql->execute(array($uid)); $data = $sql->fetch(); $arr = json_decode($data['json'], true); return $arr[$key]; } 

其中$ key是我们需要该值的JSON数组的关键字。

在我看来,回答这个问题的每个人都很友善 – 错过了一个重要的问题,除了@deceze – 使用正确的工具来完成这项工作 。 您可以强制关系数据库存储几乎任何types的数据,您可以强制Mongo处理关系数据,但费用是多less? 最终,从架构devise到应用程序代码,在各个开发和维护级别中引入了复杂性; 更不用说性能受到打击了。

在2014年,我们可以访问许多处理特定types数据的数据库服务器。

  • Mongo(文件存储)
  • Redis(键值数据存储)
  • MySQL / Maria / PostgreSQL / Oracle / etc(关系数据)
  • CouchDB(JSON)

我确定我错过了一些其他的,比如RabbirMQ和Cassandra。 我的意思是,使用正确的工具来存储你需要的数据。

如果您的应用程序需要存储和检索各种数据,真的非常快,(谁也不会)不会回避为应用程序使用多个数据源。 大多数stream行的Web框架都支持多个数据源(Rails,Django,Grails,Cake,Zend等)。 此策略将复杂性限制在应用程序的一个特定区域,ORM或应用程序的数据源界面。

早期支持在MySQL中存储JSON已被添加到MySQL 5.7.7 JSON实验室版本 ( Linux二进制文件 , 源代码 )! 该版本似乎已经从2013年公开发布的一系列与JSON相关的用户定义函数发展而来。

这种初始的本机JSON支持似乎正朝着一个非常积极的方向前进,包括INSERT上的JSONvalidation,这是一个优化的二进制存储格式,包括前导中的查找表,允许JSN_EXTRACT函数执行二进制查找,而不是在每个访问上进行parsing。 还有一大堆用于处理和查询特定JSON数据types的新函数:

 CREATE TABLE users (id INT, preferences JSON); INSERT INTO users VALUES (1, JSN_OBJECT('showSideBar', true, 'fontSize', 12)); SELECT JSN_EXTRACT(preferences, '$.showSideBar') from users; +--------------------------------------------------+ | id | JSN_EXTRACT(preferences, '$.showSideBar') | +--------------------------------------------------+ | 1 | true | +--------------------------------------------------+ 

恕我直言,以上是这个新function的一个很好的用例; 许多SQL数据库已经有一个用户表,而不是进行无尽的模式更改以适应不断变化的用户首选项,只有一个JSON列是完美的。 尤其是因为它不太可能需要查询个别项目。

虽然现在还处于初期阶段,但是MySQL服务器团队正在通过 博客进行更改。

JSON在PostgreSQL数据库中也是一个有效的数据types。 但是,MySQL数据库尚未正式支持JSON。 但它的烘焙: http : //mysqlserverteam.com/json-labs-release-native-json-data-type-and-binary-format/

我也同意,有很多有效的情况下,有些数据最好被序列化为数据库中的string。 主要的原因可能是它没有经常被查询,当它自己的模式可能会改变 – 你不想改变对应的数据库模式。 第二个原因是当序列化string直接来自外部来源时,您可能不想分析所有这些string,并且不惜任何代价地加载数据库,直到您使用任何代码。 因此,我将等待新的MySQL版本支持JSON,因为它将更容易在不同的数据库之间切换。

我用json来logging一个项目的任何内容,实际上我使用了三个表格! 一个用于json中的数据,一个用于json结构的每个元数据的索引(每个元数据由唯一的id编码),一个用于会话用户,就是这样。 基准不能在这个早期的代码状态下被量化,但是例如我是用户视图(内部连接有索引)来获得一个类别(或者任何东西,作为用户,…),而且非常慢(非常慢,在MySQL中使用视图不是好的方法)。 在这个结构中,search模块可以做任何我想做的事情,但是,我认为mongodb在这个完整的json数据logging的概念中会更有效率。 以我的例子来说,我用户的观点来创build分类树,面包屑,我的上帝! 这么多的查询来做! Apache本身走了! 实际上,对于这个小小的网站,我用的是知道生成树和面包屑的php,数据的提取是由search模块(只使用索引)完成的,数据表只用于更新。 如果我愿意的话,我可以销毁所有的索引,并用每个数据重新生成索引,然后做相反的工作,例如销毁所有的数据(json),并只用索引表重新生成索引。 我的项目是年轻的,运行在php和mysql下,但是,有时候我使用node js和mongodb这个项目会更有效率。

如果你认为你可以这样做,那就使用json,只是为了做到这一点,因为你可以! 如果这是一个错误,就忘记了; 尝试通过做出好的或不好的select,但尝试!

一个法国用户

我相信将JSON存储在一个mysql数据库中实际上会破坏使用RDBMS的目的,因为它是打算使用的。 我不会将它用在任何可能会被操纵或报告的数据中,因为这不仅会增加复杂性,而且还会影响性能,这取决于它的使用方式。

然而,我很好奇,如果有其他人想到一个可能的原因,实际上做到这一点。 我正在考虑为logging目的做一个例外。 在我的情况下,我想logging具有可变数量的参数和错误的请求。 在这种情况下,我想使用表格来处理请求types,并且使用获取的不同值的JSONstring来请求自己。

在上述情况下,这些请求被logging下来,并且不会在JSONstring字段中被操纵或索引。 但是,在更复杂的环境中,我可能会尝试使用对此类数据有更多意图的东西,并将其与该系统一起存储。 正如其他人所说,这实际上取决于你正在努力完成什么,但遵循标准总是有助于长寿和可靠!

你可以使用这个要点: https : //gist.github.com/AminaG/33d90cb99c26298c48f670b8ffac39c3

在安装到服务器(只需要root权限不超)后,你可以这样做:

select extract_json_value('{"a":["a","2"]}','(/a)')

它会返回a 2你可以使用这个返回JSON里面的任何东西。好的部分是它支持MySQL 5.1,5.2,5.6。 而且你不需要在服务器上安装任何二进制文件。

基于旧的项目common-schema ,但它仍然在今天工作https://code.google.com/archive/p/common-schema/