我认为这是件好事.所以,我从来没有这样做过.然后我看到FriendFeed做到了这一点并且实际上使他们的DB规模更好并且减少了延迟.我很好奇我是否应该这样做.如果是这样,那么正确的方法是什么?
基本上,什么是学习如何将所有内容存储在MySQL中作为CouchDB类DB的好地方?将所有内容存储为JSON似乎更容易,更快(不构建,减少延迟).
此外,在DB上存储为JSON的内容是否易于编辑,删除等?
每个人评论似乎都是从错误的角度来看这个,通过PHP在关系数据库中存储JSON代码是很好的,实际上加载和显示这样的复杂数据会更快,但是你会有设计考虑因素,比如搜索,索引等
这样做的最好方法是使用混合数据,例如,如果你需要根据日期时间进行搜索,MySQL(性能调整)将比PHP快得多,而且搜索场地的距离也应该是很多的MySQL更快(注意搜索不访问).然后,您不需要搜索的数据可以以JSON,BLOB或您认为必要的任何其他格式存储.
您需要访问的数据非常容易存储为JSON,例如基本的每个案例的发票系统.如果你有正确的HTML表单结构,它们根本不会从RDBMS中受益很多,只能通过json_encoding($ _ POST ['entires'])存储在JSON中.
我很高兴你使用MongoDB很开心,我希望它能继续为你服务,但是不要认为MySQL总是不受你的关注,因为你的应用程序的复杂性增加你可能最终需要一个RDBMS一些功能和特性(即使它只是用于退出存档数据或业务报告)
MySQL 5.7现在支持类似于MongoDB和其他无模式文档数据存储的本机JSON数据类型:
JSON支持
从MySQL 5.7.8开始,MySQL支持本机JSON类型.JSON值不存储为字符串,而是使用允许对文档元素进行快速读取访问的内部二进制格式.存储在JSON列中的JSON文档会在插入或更新时自动验证,并且无效文档会产生错误.JSON文档在创建时进行了规范化,可以使用大多数比较运算符进行比较,例如=,<,<=,>,> =,<>,!=和<=>; 有关受支持的运算符以及MySQL在比较JSON值时遵循的优先级和其他规则的信息,请参阅JSON值的比较和排序.
MySQL 5.7.8还引入了许多用于处理JSON值的函数.这些功能包括这里列出的功能:
创建JSON值的函数:JSON_ARRAY(),JSON_MERGE()和JSON_OBJECT().请参见第12.16.2节"创建JSON值的函数".
搜索JSON值的函数:JSON_CONTAINS(),JSON_CONTAINS_PATH(),JSON_EXTRACT(),JSON_KEYS()和JSON_SEARCH().请参见第12.16.3节"搜索JSON值的函数".
修改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值的函数".
提供有关JSON值的信息的函数:JSON_DEPTH(),JSON_LENGTH(),JSON_TYPE()和JSON_VALID().请参见第12.16.5节"返回JSON值属性的函数".
在MySQL 5.7.9及更高版本中,您可以使用column-> path作为JSON_EXTRACT(列,路径)的简写.这可以作为列的别名,只要在SQL语句中可以出现列标识符,包括WHERE,ORDER BY和GROUP BY子句.这包括SELECT,UPDATE,DELETE,CREATE TABLE和其他SQL语句.左侧必须是JSON列标识符(而不是别名).右侧是引用的JSON路径表达式,它根据作为列值返回的JSON文档进行评估.
有关 - >和JSON_EXTRACT()的更多信息,请参见第12.16.3节"搜索JSON值的函数".有关MySQL 5.7中的JSON路径支持的信息,请参阅搜索和修改JSON值.另请参见二级索引和虚拟生成的列.
更多信息:
https://dev.mysql.com/doc/refman/5.7/en/json.html
CouchDB和MySQL是两种非常不同的野兽.JSON是在CouchDB中存储东西的本地方式.在MySQL中,您可以做的最好的事情是将JSON数据作为文本存储在单个字段中.这完全违背了将其存储在RDBMS中的目的,并且会使每个数据库事务复杂化.
别.
话虽如此,FriendFeed似乎在MySQL之上使用了极其自定义的架构.这实际上取决于你想要存储什么,关于如何滥用数据库系统几乎没有一个明确的答案,所以它对你有意义.鉴于文章非常陈旧,他们反对Mongo和Couch的主要原因是不成熟,如果MySQL没有为你剪掉它,我会重新评估这两个.他们现在应该已经成长了很多.
json字符在存储,字符等方面没有什么特别之处
{
,}
,[
,]
,'
,a-z
,0-9
......真的没什么特别的,并且可以存储为文本.
你要遇到的第一个问题就是这个问题
{profile_id:22,用户名:'Robert',密码:'skhgeeht893htgn34ythg9er'}
存储在数据库中的更新并不是那么简单,除非你有自己的进行并为mysql开发了一个jsondecode
UPDATE users SET JSON(user_data,'username') = 'New User';
所以当你不能这样做时,你必须首先选择json,解码它,更改它,更新它,所以从理论上讲你可能会花更多的时间来构建一个合适的数据库结构!
我确实使用json来存储数据,但只使用Meta Data,不经常更新的数据,与用户特定的相关...例如,如果用户添加帖子,并且在该帖子中他添加了图像,解析图像并创建拇指和然后使用json格式的拇指网址.
为了说明使用查询获取JSON数据有多困难,我将分享我为处理此问题而进行的查询.
它不考虑数组或其他对象,只考虑基本数据类型.您应该将列的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所提到的,不要指望能够将这些数据与已经规范化的其他数据相结合.
这是一个老问题,但我仍然可以在谷歌搜索结果的顶部看到这一点,所以我想在提出问题4年后添加一个新答案是有意义的.
首先,在RDBMS中存储JSON有更好的支持.您可以考虑切换到PostgreSQL(尽管MySQL自v5.7.7起支持JSON).PostgreSQL使用与MySQL非常相似的SQL命令,除了它们支持更多功能.他们添加的一个功能是它们提供JSON数据类型,您现在可以查询存储的JSON.(有些参考)如果您没有直接在程序中编写查询,例如,在php中使用PDO或在Laravel中使用eloquent,您只需在服务器上安装PostgreSQL并更改数据库连接设置即可.您甚至不需要更改代码.
大多数时候,正如其他答案所建议的那样,将数据直接存储在RDBMS中并不是一个好主意.但有一些例外.我能想到的一种情况是具有可变数量的链接条目的字段.
例如,为了存储博客文章的标签,通常需要有一个博客文章表,一个标签表和一个匹配表.因此,当用户想要编辑帖子并且您需要显示哪个标签与该帖子相关时,您将需要查询3个表格.如果匹配的表/标签表很长,这将大大损害性能.
通过将标记作为JSON存储在博客帖子表中,相同的操作仅需要单个表搜索.然后,用户将能够更快地看到要编辑的博客帖子,但如果您要报告哪些帖子链接到标签,或者可能按标签搜索,则会损害性能.
您也可以尝试对数据库进行反规范化.通过复制数据并以两种方式存储数据,您可以获得两种方法的好处.您只需要更多的时间来存储数据和更多的存储空间(与更高的计算能力相比,这是便宜的)
我想说的唯一两个理由是:
使用标准化方法,性能不够好
您无法轻易建模出特别流畅/灵活/变化的数据
我在这里写了一些关于我自己的方法:
使用NoSQL数据存储时遇到了哪些可伸缩性问题?
(见最佳答案)
即使JSON不够快,我们也使用了自定义文本格式方法.工作/继续为我们工作.
有没有理由你没有使用像MongoDB这样的东西?(可能是MySQL是"必需的";只是好奇)
在我看来,每个回答这个问题的人都会错过一个关键问题,除了@deceze - 使用正确的工具来完成工作.您可以强制关系数据库存储几乎任何类型的数据,您可以强制Mongo处理关系数据,但代价是什么?从架构设计到应用程序代码,您最终会在各个级别的开发和维护中引入复杂性; 更不用说性能打击了.
2014年,我们可以访问许多数据库服务器,这些服务器非常好地处理特定类型的数据.
Mongo(文件存储)
Redis(键值数据存储)
MySQL/Maria/PostgreSQL/Oracle/etc(关系数据)
CouchDB(JSON)
我敢肯定我错过了其他一些人,比如RabbirMQ和Cassandra.我的观点是,使用正确的工具来存储您需要的数据.
如果您的应用程序需要真正,非常快速地存储和检索各种数据,(并且没有)不要回避为应用程序使用多个数据源.最流行的Web框架提供对多个数据源(Rails,Django,Grails,Cake,Zend等)的支持.此策略将复杂性限制为应用程序的一个特定区域,ORM或应用程序的数据源接口.
这是一个保存/更新列中JSON数组的键的函数,以及另一个检索JSON值的函数.假设存储JSON数组的列名是json,创建此函数.它正在使用PDO.
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 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数组的键.