MySQL 5.7-JSON索引-使用非标量值生成列

MySQL 5.7-JSON索引-使用非标量值生成列,mysql,json,mysql-5.7,Mysql,Json,Mysql 5.7,我一直在使用MySQL 5.7中的JSON支持。我对为索引而生成的列有几个问题 具体地说,请参考这一行: 无法为JSON列编制索引。您可以在生成的列上创建一个索引,从JSON列中提取标量值,从而绕过此限制 这对我来说似乎是一个很大的限制。无论我去哪里,人们都建议使用生成的列。但这种变通方法只适用于非常有限的一组用例。或者,我理解错了什么 搭建舞台 让我解释一下我的用例。假设您有一个名为standards的表。其结构如下: CREATE TABLE `standards` ( `id` int

我一直在使用MySQL 5.7中的JSON支持。我对为索引而生成的列有几个问题

具体地说,请参考这一行:

无法为JSON列编制索引。您可以在生成的列上创建一个索引,从JSON列中提取标量值,从而绕过此限制

这对我来说似乎是一个很大的限制。无论我去哪里,人们都建议使用生成的列。但这种变通方法只适用于非常有限的一组用例。或者,我理解错了什么

搭建舞台 让我解释一下我的用例。假设您有一个名为
standards
的表。其结构如下:

CREATE TABLE `standards` (
  `id` int(11) NOT NULL,
  `name` varchar(100) NOT NULL,
  `sections` json DEFAULT NULL,
  `subjects` json DEFAULT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
部分
列包含一个JS对象数组:

[
  {
    "id": 90491,
    "name": "A",
  },
  {
    "id": 90494,
    "name": "B",
  }
]
subjects
列包含嵌套的JS对象:

{
  "576845": {
    "id": 576845,
    "name": "Computer Education"
  },
  "576848": {
    "id": 576848,
    "name": "English Language"
  },
  "576854": {
    "id": 576854,
    "name": "Environmental Science"
  },
  "576860": {
    "id": 576860,
    "name": "Mathematics"
  }
}
示例查询 问题1 要查找具有
90494
section ID
Standard
记录,查询如下:

SELECT * from standards WHERE JSON_CONTAINS( sections->>'$[*].id', '90494' );
SELECT * from standards WHERE JSON_CONTAINS_PATH( subjects, 'one', '$."576854"');
问题2 要查找具有
576854
subject ID
Standard
记录,查询如下:

SELECT * from standards WHERE JSON_CONTAINS( sections->>'$[*].id', '90494' );
SELECT * from standards WHERE JSON_CONTAINS_PATH( subjects, 'one', '$."576854"');

问题 现在,所有这些都起作用了。问题是查询执行完整的表扫描

考虑上面的查询1,如何生成包含所有
节ID的标量数据的虚拟列

每个
标准
记录都有多个
,带有多个ID。所以,我不能仅仅创建一个整数虚拟列来存储单个值。它必须是一个节ID数组,我们需要通过它进行搜索

因此,我生成的专栏如下所示:

ALTER TABLE standards
ADD section_ids json GENERATED ALWAYS AS (sections->>'$[*].id') VIRTUAL NOT NULL;
生成的列现在只存储节ID的数组。但是我不能在生成的列上添加索引,因为它也是一个JSON列

问题-如何利用索引? 所以,问题归结到这一点——对于上面显示的查询,如何避免全表扫描


任何建议都将不胜感激。

我不会说MySQL 5.7不可能做到这一点,因为它有着笨拙的解决方法和局限性,但我不会讨论如何使用该版本,因为它要困难得多,而且在许多情况下,如果可以将大量项添加到阵列中,就会达到这些局限性

但是,从现在支持的MySQL开始,这是可能的

**请注意,
$.*
将获取所有对象属性,并返回格式化为数组的每个对象的查询值(
.id

EXPLAIN SELECT * from standards WHERE JSON_CONTAINS( sections->'$[*].id', '90494' );
EXPLAIN SELECT * from standards WHERE JSON_CONTAINS( subjects->'$.*.id', 576854 );

您将看到索引用于这些查询。

在旧版本中,我将通过手动创建一个单独的索引表,并使用触发器使其保持最新状态来解决这个问题。

目前在MySQL中不可行,请参阅。这太遗憾了。在您链接到的博客中,作者在3天前评论说,“JSON数组索引”仍然“在路线图上”。所以,我想这不会很快得到支持。