我认为这是新手想做的事情。所以,我从未尝试过。然后我看到FriendFeed这样做并成功地使他们的数据库扩展得更好并减少了延迟。我很好奇是否应该这样做。如果是这样,应该怎么做才算正确呢?
基本上,有什么好的方法可以学习如何将所有内容存储在MySQL中,就像在CouchDB中一样?将所有内容存储为JSON似乎会更容易和更快(不需要构建,延迟更小)。
此外,以JSON格式存储在数据库中的内容是否容易进行编辑、删除等操作?
我认为这是新手想做的事情。所以,我从未尝试过。然后我看到FriendFeed这样做并成功地使他们的数据库扩展得更好并减少了延迟。我很好奇是否应该这样做。如果是这样,应该怎么做才算正确呢?
基本上,有什么好的方法可以学习如何将所有内容存储在MySQL中,就像在CouchDB中一样?将所有内容存储为JSON似乎会更容易和更快(不需要构建,延迟更小)。
此外,以JSON格式存储在数据库中的内容是否容易进行编辑、删除等操作?
评论者们似乎从错误的角度来看待这个问题,使用 PHP 将 JSON 代码存储在关系型数据库中是可以的,而且实际上加载和显示复杂数据会更快。但是您需要考虑搜索、索引等设计问题。
最好的方法是使用混合数据,例如如果您需要基于日期时间进行搜索,则经过性能调整的 MySQL 系统将比 PHP 更快,并且对于搜索场馆距离这样的内容,MySQL 也应该会更快(注意搜索而不是访问)。 您不需要搜索的数据可以存储为 JSON、BLOB 或任何其他您认为必要的格式。
需要访问的数据非常容易以 JSON 格式存储,例如一个基本的按案例发票系统。 它们并不会受益于 RDBMS,通过正确的 HTML 表单结构,可以仅通过 json_encoding($ _POST ['entires'])将其存储为 JSON。
我很高兴您喜欢使用 MongoDB,并希望它可以继续为您服务,但请不要认为 MySQL 总是会被您遗忘,随着您的应用程序变得越来越复杂,您可能需要某些功能和特性的 RDBMS(即使仅用于退休归档数据或业务报告)。
MySQL 5.7现在支持原生JSON数据类型,类似于MongoDB和其他无模式文档数据存储:
JSON支持
从MySQL 5.7.8开始,MySQL支持原生的JSON类型。 JSON值不以字符串形式存储,而是使用内部二进制格式存储,可以快速读取文档元素。 存储在JSON列中的JSON文档在插入或更新时会自动进行验证,无效的文档会产生错误。 JSON文档在创建时会进行规范化,并且可以使用大多数比较运算符进行比较,例如=,<,<=,>,>=,<>,!=和<=>;有关受支持的运算符以及MySQL在比较JSON值时遵循的优先级和其他规则的信息,请参见“比较和排序JSON值”。
MySQL 5.7.8还引入了许多用于处理JSON值的函数。 这些函数包括以下内容:
在MySQL 5.7.9及更高版本中,您可以使用column->path作为JSON_EXTRACT(column, path)的简写。这在SQL语句中的任何列标识符出现的地方都可以用作列的别名,包括WHERE、ORDER BY和GROUP BY子句,以及SELECT、UPDATE、DELETE、CREATE TABLE和其他SQL语句。左侧必须是一个JSON列标识符(而不是一个别名)。右侧是一个带引号的JSON路径表达式,该表达式针对返回的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值属性的函数”。
有关“->”和JSON_EXTRACT()的更多信息,请参见第12.16.3节“搜索JSON值的函数”。有关MySQL 5.7中JSON路径支持的信息,请参见“搜索和修改JSON值”。还请参见二级索引和虚拟生成列。
更多信息请见:https://dev.mysql.com/doc/refman/5.7/en/json.html
就存储而言,JSON字符并没有什么特殊之处,例如 {
,}
,[
,]
,'
,a-z
,0-9
等字符可以被当作文本进行存储。
但是遇到下面这个问题:
{ profile_id: 22, username: 'Robert', password: 'skhgeeht893htgn34ythg9er' }
将这个存储在数据库中时,更新操作并不简单,除非您自己编写过程并为MySQL开发了jsondecode工具。
UPDATE users SET JSON(user_data,'username') = 'New User';
因此,由于你不能这样做,你必须首先选择json,解码它,更改它,然后更新它,因此理论上你可能要花更多的时间构建一个合适的数据库结构!
我确实使用json存储数据,但只用于元数据,即不经常更新的数据,与用户特定内容无关...例如,如果用户添加了一篇文章,并在其中添加了图像,则我将解析图像并创建缩略图,然后使用缩略图的URL以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'
这是一个旧问题,但我仍然能够在谷歌搜索结果的顶部看到它,所以我猜在问题提出四年后添加一个新答案会很有意义。
首先,关系数据库管理系统中存储JSON的支持更好。您可以考虑切换到PostgreSQL(尽管MySQL自v5.7.7以来已支持JSON)。PostgreSQL使用非常类似于MySQL的SQL命令,除了他们支持更多的功能。他们添加的其中一个功能是提供JSON数据类型,您现在可以查询存储的JSON。(一些参考资料)如果您没有直接在程序中组合查询,例如在php中使用PDO或在Laravel中使用Eloquent,则只需要在服务器上安装PostgreSQL并更改数据库连接设置即可。您甚至不需要更改代码。
大多数时候,正如其他答案建议的那样,在关系数据库管理系统中直接存储数据作为JSON不是一个好主意。但也有一些例外情况。我可以想到的一个情况是具有可变数量链接条目的字段。
例如,对于存储博客文章标签,通常需要一个博客文章表、一个标签表和一个匹配表。因此,当用户要编辑帖子并且需要显示与该帖子相关的标签时,您将需要查询3个表。如果匹配表/标签表很长,这将严重影响性能。
通过将标签作为JSON存储在博客文章表中,相同的操作只需要进行单个表搜索。然后用户将能够更快地查看要编辑的博客文章,但是如果您想制作一个链接到标签的报告,或者按标签搜索,则会损害性能。
您还可以尝试去规范化数据库。通过复制数据并以两种方式存储数据,您可以获得两种方法的好处。您只需要花费更多的时间存储数据和更多的存储空间(与更多的计算能力成本相比,存储空间是便宜的)
这取决于你的使用情况。如果你存储的信息在报告中没有任何价值,也不会通过与其他表的JOIN查询进行查询,那么将数据作为JSON编码存储在单个文本字段中可能是有意义的。
这可以极大地简化您的数据模型。但是,正如RobertPitt所提到的,不要期望能够将此数据与已经规范化的其他数据组合在一起。
What scalability problems have you encountered using a NoSQL data store?
(请参见顶部答案)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数组的键。
SELECT FOR UPDATE
或者在 JSON 数据中进行版本控制等锁定机制。 - DhruvPathakSELECT FOR UPDATE
更新答案,以使其更好?我不知道如何使用它。 - Subinjson_decode
和json_encode
存储和检索数据。 - Salem