我应该何时将数据存储为JSON?

时间:2018-02-20 20:55:47

标签: mysql database laravel database-design relational-database

这是较长的一个如此扣: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_addressbased_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_addressbased_in_country属于同一个对象based_in)。

我也可以采用混合方法,结合第一种和第三种方法;创建一个1:n表,将JSON存储在其值列中。

然后,让我们说我还想添加他们喜欢的颜色:P - 它会是新表,新列,新行还是新对象?

在性能,可伸缩性和灵活性方面,哪种方法最适用于不经常检索的相关数据(通常可能会更改,因为可能会添加新密钥以存储其他详细信息)?

我们何时创建相关表而不是为1:1关系创建新列(特别是自MySQL中出现JSON以来)?

最终,我应该何时将数据存储为JSON?

P.S。虽然我理解NoSQL可能能够解决这个问题,但我正在寻找MySQL的答案!

1 个答案:

答案 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