MySql JSON 数据类型的用例
Posted
技术标签:
【中文标题】MySql JSON 数据类型的用例【英文标题】:A use case for MySql JSON datatype 【发布时间】:2019-01-20 16:01:30 【问题描述】:我正在为一个网站创建一个数据库模式,用户可以在该网站上编写Articles
。我几乎完成了设计,突然间我在mysql
JSON datatype
上读了几篇博客。
根据博客,在某些用例中可以使用 JSON
:
-
用于存储元数据。例如,具有高度、宽度的产品,
颜色存储为 JSON。
用于存储非标准模式类型数据
用于将标签存储为 JSON。例如这个问题可能有标签 -
mysql,JSON。所以博客推荐使用 JSON 结构
拥有所有
tags
。
最后一个对我来说是可疑的。为什么?
好的,我已将 JSON 中的标签值存储为"tags": ["mysql", "JSON", "mysql-datatype"]
。我同意这有助于轻松维护文章的标签。
但是假设一个用户想要阅读所有与mysql
标签相关的文章!!如果我为article_id
- tags_id
维护了一个单独的表,我可以根据tags
轻松获得所有Articles
。但是对于JSON
,这可能是一个非常忙碌的要求,尽管这可以解决但需要付出代价。当然查询速度较慢。
这是我的文章架构:
我的思维方式是正确的还是我在这里遗漏了什么?喜欢听一些建议。
【问题讨论】:
我强烈建议不要将 JSON 数据用于您可能想要搜索的任何内容。 MySQL 中可用的功能不够强大。而是保留单独的表格。 我认为你的想法令人耳目一新的'钱' @Strawberry '赚钱' - 我没听懂! 【参考方案1】:您尝试执行的任务是将文章与标签关联起来,最好将其处理为多对多关系。为此,您需要另一个表,我相信它是图表中的 article_tags
表。
这使得查询具有给定标签的所有文章变得容易。
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
如果在文章表中使用 JSON 存储标签,做同样的事情是不同的:
SELECT ...
FROM article AS a
WHERE JSON_CONTAINS(a.article_tags, '1234')
这似乎更简单,因为它不需要 JOIN。
但是任何将您需要搜索的列放入函数调用的搜索都将无法使用索引。这将导致表扫描,因此查询将始终搜索表中的每一行。随着表的增长,“艰难地”执行此搜索会变得越来越慢。
article_tags
表的第一种方法使用索引有两种方式:
-
快速查找
article_tags
中与所需标签匹配的条目
通过主键快速查找对应文章
不需要表扫描。查询仅读取将出现在查询结果中的行。
我对 JSON 数据类型和 JSON 函数的看法遵循以下一般规则:
在选择列表中引用 JSON 列,但不在 WHERE 子句中。
也就是说,如果您可以使用非 JSON 列在 WHERE 子句中执行搜索条件,则可以利用索引使查询尽可能高效。
一旦以这种方式找到相关行,您就可以提取部分 JSON 数据以在结果中返回。与在表扫描中搜索 JSON 文档的成本相比,从与您的搜索匹配的行上的 JSON 文档中提取字段的成本相对较小。
除非符合搜索条件,否则不会评估选择列表的行。
【讨论】:
使用 JSON 而不是为该数据设置多列是否有任何性能优势?我认为这节省了一些数据库空间,请纠正我。 不,JSON 在我的测试中平均占用 两倍空间 来获取等效数据。请参阅我的演示文稿How to Use JSON in MySQL Wrong,幻灯片 52-59 是关于存储的。【参考方案2】:我自己还没有使用过它,但据我了解,我不会将 JSON 用于您想要查找/过滤的项目。例如:我会用它来存储配置架构可能经常更改的 JSON 配置(这意味着没有数据库架构更改)。
不过,MySQL 似乎确实具有在 JSON 中搜索的功能,https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html
JSON_CONTAINS(target, candidate[, path])
不确定与索引字符串列相比的效率。
【讨论】:
以上是关于MySql JSON 数据类型的用例的主要内容,如果未能解决你的问题,请参考以下文章