这是较长的一个如此扣:P!
考虑用户表。它有ID,密码,电子邮件和一些时间戳。现在,假设我想存储更多信息,例如它们所在的位置(或任何其他不经常检索的数据)。我可以将它作为JSON(伪代码)
存储在users表的新列中{based_in: {address: "here", country:"xx", region: "great"}}
或者我可以创建一个存储该信息的1:1相关user_location表。
CREATE TABLE `user_based_in` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`address` int(11) DEFAULT NULL,
`country` int(11) DEFAULT NULL,
`region` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
最后,我还可以创建一个1:n相关表(user_info),它可以以键值格式保存这些数据,例如: based_in_address
,based_in_country
。
CREATE TABLE `user_info` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`key` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`value` text COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `user_meta_key_index` (`key`)
)
使用第一种方法,我可以添加有关用户的新细节,而无需修改后端 - 这样很酷。但是当我添加更多细节时,我觉得它变得很乱。
使用第二种方法,我想我会得到更好的索引,但这意味着每次我想要存储新的用户细节时都必须调整后端。
使用第三种方法,我还可以在不改变后端的情况下添加新的细节(键) - 但这个解决方案对我来说有点难看,因为它会产生很多行并且不能相关(在上面的示例中,只有前两个选项明确指出based_in_address
和based_in_country
属于同一个对象based_in
)。
我也可以采用混合方法,结合第一种和第三种方法;创建一个1:n表,将JSON存储在其值列中。
然后,让我们说我还想添加他们喜欢的颜色:P - 它会是新表,新列,新行还是新对象?
在性能,可伸缩性和灵活性方面,哪种方法最适用于不经常检索的相关数据(通常可能会更改,因为可能会添加新密钥以存储其他详细信息)?
我们何时创建相关表而不是为1:1关系创建新列(特别是自MySQL中出现JSON以来)?
最终,我应该何时将数据存储为JSON?
P.S。虽然我理解NoSQL可能能够解决这个问题,但我正在寻找MySQL的答案!
答案 0 :(得分:1)
最终,我应该何时将数据存储为JSON?
当您的数据可能不适合整齐的类型列系统时,会出现JSON类型。如果您不确定要在表格中添加哪些数据,则应该使用 谨慎 。或者,当数据本质上是非结构化的时,这比键/值表更灵活。
在您的示例中,您非常确定要存储的内容:位置信息。这是一个非常明确的问题,它由user_based_in
表处理得很好。
何时使用JSON的一个很好的示例可能是将命中记录到API端点。参数由每个API端点决定,表格无法知道。
create table api_log (
id integer primary key auto_increment,
endpoint text not null,
when timestamp not null,
params json not null
);
A Practical Guide to MySQL JSON Data Type By Example使用类似的方案。
另一个例子可能是您不确定您可能想要收集哪些其他数据。
create table stuff (
...normal table design...
other json
);
这允许应用程序推测性地存储其他数据,使用它,并查看它是否是他们想要添加到结构中的东西。确定给定的键/值很重要后,将其作为列添加到表中,并将数据从JSON传输到新列。这为您提供了传统关系数据库的所有好处。
让我们说我们认为things
很重要。我们制作了一个新的things
列。将其设置为other->>'$.things'
。并从JSON列中删除things
以避免数据冗余。
alter table stuff add column things text;
update stuff
set things = other->>'$.things',
other = json_remove(other, '$.things')
where other is not null