MySql JSON 数据类型的用例
A use case for MySql JSON datatype
我正在为一个网站创建数据库架构,用户可以在该网站上编写 Articles
。我几乎完成了设计,突然我在 MySQL
.
中阅读了一些关于 JSON datatype
的博客
根据博客,在某些情况下可以使用 JSON
:
- 用于存储元数据。例如,具有高度、宽度的产品,
颜色存储为 JSON.
- 用于存储非标准架构类型数据
- 用于将标签存储为 JSON。例如这个问题可能有标签 -
mysql、JSON。所以博客推荐使用 JSON 结构
拥有所有
tags
.
最后一个我很怀疑。为什么?
好的,我已将 JSON 中的标签值存储为 {"tags": ["mysql", "JSON", "mysql-datatype"]}
。我同意这有助于轻松维护文章的标签。
但是假设用户想要阅读所有与 mysql
标签相关的文章!!如果我一直为 article_id
- tags_id
维护一个单独的 table,我可以很容易地得到所有基于 tags
的 Articles
。但是对于 JSON
这可能是一个非常繁忙的要求,虽然这可以解决但需要付出代价。当然查询速度较慢。
这是我的文章架构:
我的思维方式是正确的还是我在这里遗漏了什么?喜欢听一些建议。
我自己还没有使用过它,但根据我的理解,我不会将 JSON 用于您想要查找/过滤的项目。例如:我会用它来存储 JSON 配置,其中配置架构可能会经常更改(意味着没有数据库架构更改)。
不过看起来 MySQL 确实具有在 JSON、https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html
中搜索的功能
JSON_CONTAINS(target, candidate[, path])
与索引字符串列相比,不确定它的效率。
您尝试执行的任务是将文章与标签相关联,最好将其处理为多对多关系。为此,您需要另一个 table,我认为它是图表中的 article_tags
table。
这样可以轻松查询具有给定标签的所有文章。
SELECT ...
FROM article AS a
JOIN article_tags AS t USING (article_id)
WHERE t.topic_id = 1234 -- whatever is the id for the topic you want to read
如果在文章table中使用JSON存储标签,做同样的事情是不同的:
SELECT ...
FROM article AS a
WHERE JSON_CONTAINS(a.article_tags, '1234')
这可能看起来更简单,因为它不需要 JOIN。
但是任何将您需要搜索的列放在函数调用中的搜索都将无法使用索引。这将导致 table 扫描,因此查询将始终搜索 table 中的每一行。随着您的 table 的增长,执行此搜索的速度会越来越慢 "the hard way."
article_tags
table 的第一种方法使用两种方式使用索引:
- 在
article_tags
中快速查找匹配所需标签的条目
- 通过主键快速查找对应文章
不需要table-扫描。查询只读取将要出现在查询结果中的行。
我对 JSON 数据类型和 JSON 函数的理解遵循以下一般规则:
引用 select 列表中的 JSON 列,但不在 WHERE 子句中。
也就是说,如果您可以使用非 JSON 列在 WHERE 子句中执行搜索条件,则可以利用索引使查询尽可能高效。
通过这种方式找到相关行后,您可以将部分 JSON 数据提取到结果中的 return。与在 table 扫描中搜索 JSON 文档的成本相比,从匹配您的搜索的行上的 JSON 文档中提取字段的成本相对较小。
不对 select-列表中的行进行评估,除非它们与搜索条件匹配。
我正在为一个网站创建数据库架构,用户可以在该网站上编写 Articles
。我几乎完成了设计,突然我在 MySQL
.
中阅读了一些关于 JSON datatype
的博客
根据博客,在某些情况下可以使用 JSON
:
- 用于存储元数据。例如,具有高度、宽度的产品, 颜色存储为 JSON.
- 用于存储非标准架构类型数据
- 用于将标签存储为 JSON。例如这个问题可能有标签 -
mysql、JSON。所以博客推荐使用 JSON 结构
拥有所有
tags
.
最后一个我很怀疑。为什么?
好的,我已将 JSON 中的标签值存储为 {"tags": ["mysql", "JSON", "mysql-datatype"]}
。我同意这有助于轻松维护文章的标签。
但是假设用户想要阅读所有与 mysql
标签相关的文章!!如果我一直为 article_id
- tags_id
维护一个单独的 table,我可以很容易地得到所有基于 tags
的 Articles
。但是对于 JSON
这可能是一个非常繁忙的要求,虽然这可以解决但需要付出代价。当然查询速度较慢。
这是我的文章架构:
我自己还没有使用过它,但根据我的理解,我不会将 JSON 用于您想要查找/过滤的项目。例如:我会用它来存储 JSON 配置,其中配置架构可能会经常更改(意味着没有数据库架构更改)。
不过看起来 MySQL 确实具有在 JSON、https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html
中搜索的功能JSON_CONTAINS(target, candidate[, path])
与索引字符串列相比,不确定它的效率。
您尝试执行的任务是将文章与标签相关联,最好将其处理为多对多关系。为此,您需要另一个 table,我认为它是图表中的 article_tags
table。
这样可以轻松查询具有给定标签的所有文章。
SELECT ...
FROM article AS a
JOIN article_tags AS t USING (article_id)
WHERE t.topic_id = 1234 -- whatever is the id for the topic you want to read
如果在文章table中使用JSON存储标签,做同样的事情是不同的:
SELECT ...
FROM article AS a
WHERE JSON_CONTAINS(a.article_tags, '1234')
这可能看起来更简单,因为它不需要 JOIN。
但是任何将您需要搜索的列放在函数调用中的搜索都将无法使用索引。这将导致 table 扫描,因此查询将始终搜索 table 中的每一行。随着您的 table 的增长,执行此搜索的速度会越来越慢 "the hard way."
article_tags
table 的第一种方法使用两种方式使用索引:
- 在
article_tags
中快速查找匹配所需标签的条目 - 通过主键快速查找对应文章
不需要table-扫描。查询只读取将要出现在查询结果中的行。
我对 JSON 数据类型和 JSON 函数的理解遵循以下一般规则:
引用 select 列表中的 JSON 列,但不在 WHERE 子句中。
也就是说,如果您可以使用非 JSON 列在 WHERE 子句中执行搜索条件,则可以利用索引使查询尽可能高效。
通过这种方式找到相关行后,您可以将部分 JSON 数据提取到结果中的 return。与在 table 扫描中搜索 JSON 文档的成本相比,从匹配您的搜索的行上的 JSON 文档中提取字段的成本相对较小。
不对 select-列表中的行进行评估,除非它们与搜索条件匹配。