我认为这是一个n00b要做的事情。因此,我从未做到过。然后,我看到FriendFeed做到了这一点,实际上使他们的数据库扩展性更好,并减少了延迟。我很好奇我是否应该这样做。而且,如果是这样,正确的方法是什么?
基本上,什么地方是学习如何将MySQL中的所有内容存储为CouchDB类数据库的好地方?将所有内容存储为JSON似乎会变得更加轻松快捷(无需构建,延迟更短)。
另外,是否容易编辑,删除等以JSON形式存储在数据库中的内容?
我认为这是一个n00b要做的事情。因此,我从未做到过。然后,我看到FriendFeed做到了这一点,实际上使他们的数据库扩展性更好,并减少了延迟。我很好奇我是否应该这样做。而且,如果是这样,正确的方法是什么?
基本上,什么地方是学习如何将MySQL中的所有内容存储为CouchDB类数据库的好地方?将所有内容存储为JSON似乎会变得更加轻松快捷(无需构建,延迟更短)。
另外,是否容易编辑,删除等以JSON形式存储在数据库中的内容?
Answers:
CouchDB和MySQL是两个非常不同的野兽。JSON是将内容存储在CouchDB中的本地方法。在MySQL中,最好的办法是将JSON数据作为文本存储在单个字段中。这将完全违背将其存储在RDBMS中的目的,并使每个数据库事务都大大复杂化。
别。
话虽这么说,FriendFeed似乎在MySQL之上使用了极其自定义的架构。这实际上取决于您要存储的内容,关于如何滥用数据库系统几乎没有一个明确的答案,因此这对您来说很有意义。鉴于这篇文章非常老,并且反对Mongo和Couch的主要原因是不成熟,如果MySQL不适合您,我将重新评估这两点。他们现在应该已经成长很多。
每个人的评论似乎都是从错误的角度出发的,可以通过PHP将JSON代码存储在关系数据库中,实际上这样加载和显示复杂数据会更快,但是您将需要考虑以下设计问题搜索,索引等
最好的方法是使用混合数据,例如,如果您需要基于日期时间进行搜索(性能进行了调整),MySQL将比PHP快很多,并且对于诸如搜索场所距离之类的事情,MySQL也会很多。更快(通知搜索无法访问)。然后,您无需搜索的数据就可以JSON,BLOB或您真正认为必要的任何其他格式存储。
您需要访问的数据可以很容易地存储为JSON,例如基本的按需开票系统。它们根本不能从RDBMS中获得太多好处,如果您具有正确的HTML表单结构,则可以仅通过json_encoding($ _ POST ['entires'])将其存储在JSON中。
我很高兴您对使用MongoDB感到满意,并希望它继续为您服务,但不要认为MySQL总是会被您忽略,因为您的应用程序复杂性增加,您可能最终需要RDBMS一些功能和特性(即使仅用于撤回已归档的数据或业务报告)
MySQL 5.7现在支持类似于MongoDB和其他无模式文档数据存储的本机JSON数据类型:
JSON支持
从MySQL 5.7.8开始,MySQL支持本机JSON类型。JSON值不存储为字符串,而是使用内部二进制格式存储,该格式允许快速读取文档元素。每当插入或更新JSON列中存储的JSON文档时,都会自动对其进行验证,无效文档会产生错误。JSON文档在创建时已标准化,可以使用大多数比较运算符进行比较,例如=,<,<=,>,> =,<>,!=和<=>;有关在比较JSON值时支持的运算符以及MySQL遵循的优先级和其他规则的信息,请参见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(column,path)的简写。只要列标识符可以在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值。另请参见二级索引和虚拟生成的列。
更多信息:
json字符在存储时没有什么特别的,例如chars
{
,}
,[
,]
,'
,a-z
,0-9
......真的没什么特别的,并且可以存储为文本。
您要面对的第一个问题是
{profile_id:22,用户名:'Robert',密码:'skhgeeht893htgn34ythg9er'}
除非您有自己的操作程序并为mysql开发了jsondecode,否则存储在数据库中的文件并不是那么容易更新
UPDATE users SET JSON(user_data,'username') = 'New User';
因此,您不能做的是,必须首先选择json,对其进行解码,更改,更新,因此从理论上讲,您不妨花更多的时间来构建合适的数据库结构!
我确实使用json来存储数据,但仅存储元数据,即不经常更新的数据,与用户特定条件无关。例如,如果用户添加了帖子,并且在该帖子中他添加了图像,则无法解析图像并创建拇指和然后使用json格式的thumb URL。
为了说明使用查询获取JSON数据有多么困难,我将分享为处理此问题而进行的查询。
它不考虑数组或其他对象,仅考虑基本数据类型。您应该将column的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)所提到的那样,不要指望能够将此数据与已标准化的其他数据结合起来。
这是一个老问题,但是我仍然可以在Google搜索结果的顶部看到该问题,因此我认为在提出问题4年后添加一个新答案将是有意义的。
首先,在RDBMS中存储JSON有更好的支持。您可以考虑切换到PostgreSQL(尽管MySQL自v5.7.7起已支持JSON)。PostgreSQL使用与MySQL非常相似的SQL命令,但它们支持更多功能。他们添加的功能之一是它们提供JSON数据类型,您现在可以查询存储的JSON。(对此有一些参考)如果您不是直接在程序中构成查询,例如,在php中使用PDO或在Laravel中使用雄辩的话,那么您所要做的只是在服务器上安装PostgreSQL并更改数据库连接设置。您甚至不需要更改代码。
在大多数情况下,正如其他答案所建议的那样,将数据直接以JSON形式直接存储在RDBMS中并不是一个好主意。虽然有一些例外。我可以想到的一种情况是一个具有可变数量的链接条目的字段。
例如,要存储博客文章的标签,通常需要一个博客文章表,一个标签表和一个匹配表。因此,当用户想要编辑帖子时,您需要显示与该帖子相关的标签,则需要查询3个表。如果您的匹配表/标签表很长,这会严重损害性能。
通过将标签以JSON格式存储在博客文章表中,相同的操作只需要搜索一个表即可。然后,用户将能够看到博客帖子,以便更快地进行编辑,但是,如果您要报告将哪些帖子链接到标签,或者可能要按标签搜索,这将损害性能。
您也可以尝试对数据库进行非规范化。通过以两种方式复制数据并存储数据,您可以从两种方法中受益。您只需要多一点时间来存储数据和更多存储空间(与更多计算能力的成本相比,这是便宜的)
我想说的只有两个原因:
我在这里写了一些关于自己的方法的文章:
(请参见最佳答案)
甚至JSON的速度也不够快,因此我们使用了自定义文本格式方法。工作/继续为我们工作良好。
您没有使用像MongoDB这样的东西是有原因的吗?(可能是“必需的” MySQL;只是出于好奇)
在我看来,每个回答此问题的人都有点错过了一个关键问题,除了@deceze以外,请使用正确的工具进行工作。您可以强制关系数据库存储几乎任何类型的数据,并且可以强制Mongo处理关系数据,但是要花多少钱?您最终在从模式设计到应用程序代码的所有开发和维护级别上都引入了复杂性。更不用说性能打击了。
在2014年,我们可以访问许多处理特殊类型数据的数据库服务器。
我确定我想念其他一些人,例如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数组的键。
SELECT FOR UPDATE
在json数据中添加类似或版本控制的锁。
SELECT FOR UPDATE
,这样会更好。我不知道怎么用。
MySQL 5.7.7 JSON实验版本(Linux二进制文件,源代码)中已添加了对在JSON中存储JSON的早期支持!该版本似乎是从2013年公开的一系列与JSON相关的用户定义函数发展而来的。
这种新生的原生JSON支持似乎朝着非常积极的方向发展,包括在INSERT上进行JSON验证,这是一种优化的二进制存储格式,包括在序言中的查找表,该表允许JSN_EXTRACT函数执行二进制查找,而不是对每次访问进行解析。还有大量用于处理和查询特定JSON数据类型的新功能:
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 |
+--------------------------------------------------+
恕我直言,以上是此新功能的绝佳用例;许多SQL数据库已经具有一个用户表,而不是进行无休止的模式更改以适应不断发展的用户首选项集,而只需一个JSON列JOIN
就可以了。特别是因为不太可能需要针对单个项目进行查询。
我相信,将JSON存储在mysql数据库中确实会破坏使用RDBMS的目的,因为它打算被使用。我不会在任何时候进行处理或报告的数据中使用它,因为它不仅增加了复杂性,而且根据其使用方式可能很容易影响性能。
但是,我很好奇是否有人想到了这样做的可能原因。我当时正在考虑出于记录目的而设置例外。就我而言,我想记录具有可变数量的参数和错误的请求。在这种情况下,我想将表用于请求的类型,并将请求本身使用获得的具有不同值的JSON字符串。
在上述情况下,将记录请求,并且永远不会在JSON字符串字段中对请求进行操作或建立索引。但是,在更复杂的环境中,我可能会尝试使用更倾向于这种类型的数据的东西,并将其存储在该系统中。正如其他人所说,这实际上取决于您要完成的工作,但是遵循标准始终可以延长使用寿命和可靠性!
JSON在PostgreSQL数据库中也是有效的数据类型。但是,MySQL数据库尚未正式支持JSON。但这很糟糕:http : //mysqlserverteam.com/json-labs-release-native-json-data-type-and-binary-format/
我也同意,在许多有效的情况下,最好将某些数据序列化为数据库中的字符串。主要原因可能是不定期查询它的时间,并且它自己的模式可能会更改-您不想更改与此相对应的数据库模式。第二个原因是,当序列化的字符串直接来自外部来源时,您可能不希望解析所有字符串并不惜一切代价将其输入数据库,直到您使用任何形式。因此,我将等待新的MySQL版本支持JSON,因为在不同数据库之间进行切换会更容易。
我使用json记录项目的任何内容,实际上我使用了三个表!一个用于json中的数据,一个用于json结构的每个元数据的索引(每个元数据均由唯一的ID编码),另一个用于会话用户,仅此而已。在早期的代码状态下无法对基准进行量化,但是例如,我是用户视图(与索引进行内部连接)以获取类别(或其他任何形式的用户,...),而且非常慢(非常慢) ,在mysql中使用视图不是一个好方法)。在这种结构中,搜索模块可以执行我想要的任何操作,但是,我认为mongodb在完整JSON数据记录的概念上将更加高效。例如,我使用用户视图来创建类别树,面包屑,我的天!要做这么多查询!Apache本身不见了!实际上,对于这个小型网站,我使用的是一个会生成树和面包屑的php,数据的提取由搜索模块(仅使用索引)完成,数据表仅用于更新。如果我愿意,我可以销毁所有索引,并使用每个数据重新生成它,然后执行相反的工作,例如销毁所有数据(json)并仅使用索引表重新生成它。我的项目还很年轻,可以在php和mysql下运行,但是有时候我使用node js和mongodb可以使该项目更有效。
如果您认为可以做到,请使用json,因为可以做到!并且,如果它是一个错误,请忘记它;尝试做出好还是坏的选择,但是尝试!
低
法国用户
您可以使用以下要点:https://gist.github.com/AminaG/33d90cb99c26298c48f670b8ffac39c3
将其安装到服务器后(只需要root特权而不是super),您可以执行以下操作:
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/