我什么时候应该将我的数据存储为 JSON?
When should I store my data as JSON?
这是较长的一款,所以请系好安全带:P!
考虑一个用户 table。它有 ID、密码、电子邮件和一些时间戳。现在,假设我想存储更多信息,例如它们的位置(或任何其他不经常检索的数据)。我可以将它存储在用户 table 的新列中,作为 JSON(伪代码)
{based_in: {address: "here", country:"xx", region: "great"}}
或者我可以创建一个 1:1 相关的 user_location table 来存储该信息。
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 相关的 table (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 table 在其值列中存储 JSON。
然后,假设我还想添加他们最喜欢的颜色 :P - 是新 table、新列、新行还是新对象?
在性能、可扩展性和灵活性方面,哪种方法最适合不经常检索的相关数据(通常会发生变化,因为可能会添加新密钥以存储其他详细信息)?
我们什么时候创建相关的 table 而不是为 1:1 关系创建新列(尤其是自从 MySQL 中出现 JSON 以来)?
最终,我应该什么时候将数据存储为 JSON?
P.S。虽然我知道 NoSQL 可能能够解决这个问题,但我正在寻找 MySQL 答案!
Ultimately, when should I store my data as JSON?
JSON 类型适用于当您的数据可能不适合整洁的类型化列系统时。当您不确定要将什么数据放入 table 时,您应该 谨慎地使用它 。或者当数据本质上是非结构化数据时,这比 key/value table.
无限灵活
在您的示例中,您非常确定要存储什么:位置信息。这是一个定义明确的问题,您的 user_based_in
table.
很好地解决了这个问题
何时使用 JSON 的一个很好的例子可能是将点击记录到 API 端点。参数由每个 API 端点决定,table 无法知道。
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
);
这允许应用程序推测性地存储额外的数据,使用它,看看它们是否想要添加到结构中。一旦确定给定的 key/value 很重要,将其作为列添加到 table 并将数据从 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
这是较长的一款,所以请系好安全带:P!
考虑一个用户 table。它有 ID、密码、电子邮件和一些时间戳。现在,假设我想存储更多信息,例如它们的位置(或任何其他不经常检索的数据)。我可以将它存储在用户 table 的新列中,作为 JSON(伪代码)
{based_in: {address: "here", country:"xx", region: "great"}}
或者我可以创建一个 1:1 相关的 user_location table 来存储该信息。
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 相关的 table (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 table 在其值列中存储 JSON。
然后,假设我还想添加他们最喜欢的颜色 :P - 是新 table、新列、新行还是新对象?
在性能、可扩展性和灵活性方面,哪种方法最适合不经常检索的相关数据(通常会发生变化,因为可能会添加新密钥以存储其他详细信息)?
我们什么时候创建相关的 table 而不是为 1:1 关系创建新列(尤其是自从 MySQL 中出现 JSON 以来)?
最终,我应该什么时候将数据存储为 JSON?
P.S。虽然我知道 NoSQL 可能能够解决这个问题,但我正在寻找 MySQL 答案!
Ultimately, when should I store my data as JSON?
JSON 类型适用于当您的数据可能不适合整洁的类型化列系统时。当您不确定要将什么数据放入 table 时,您应该 谨慎地使用它 。或者当数据本质上是非结构化数据时,这比 key/value table.
无限灵活在您的示例中,您非常确定要存储什么:位置信息。这是一个定义明确的问题,您的 user_based_in
table.
何时使用 JSON 的一个很好的例子可能是将点击记录到 API 端点。参数由每个 API 端点决定,table 无法知道。
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
);
这允许应用程序推测性地存储额外的数据,使用它,看看它们是否想要添加到结构中。一旦确定给定的 key/value 很重要,将其作为列添加到 table 并将数据从 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