一. 创建索引
由于json有两类不同的数据形式,即:json对象(如:{"id": 1, "name":"he"}),json数组(如:["1","2","3"]),因为进行分开讲解。
1. 当字段的数据为json对象
 
例如:{"id": 1, "name":"he"}
【内容】为需要自行替换的部分
语法:ALTER Table 【表名】 ADD INDEX 索引名( ( CAST(【表中json的字段名】 as【json数据中需要创建索引的数据类型】 ARRAY) ) )
其中,【成员名对应的数据类型】自行参考数据MySQL8拥有的数据类型,例如可填:CHAR(32), UNSIGNED等。
2. 当数据为json数组
 
例如: ["1","2"]或[{"id": 1, "name":"he"},{"id": 2, "name":"zhi"}]
【内容】为需要自行替换的部分
语法:ALTER Table 【表名】 ADD INDEX 索引名( ( CAST(【表中json的字段名】 -> '$[*].【需要作为索引的json数据的成员名】' as 【成员名对应的数据类型】‘ ARRAY) ) )
其中, $[*]代表数据中的每个元素,也就是将会让所有的元素加入索引,例如:第x行的数据为["1","2"],索引中将有"1"和"2"都对应到x行;若为$[0],那么只会将每行的第一个元素加入索引。
此外,【成员名对应的数据类型】自行参考数据mysql拥有的数据类型,例如:CHAR(32), UNSIGNED等。
3. 当数据为json数组,但内部元素不为json对象
 
例如:["1","2", "3"]就是为json数组,但内部元素不为json对象的数据,使用上述的1.和2.的语法都可,推荐使用2.语义更为明确。下方的示例,展示这种特殊的情况。
二. 具体示例(内部元素不为json对象的json数组)
 
1. 表定义和数据准备
-- 创建表
DROP TABLE IF EXISTS `test`;
CREATE TABLE test ( 
	id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    jchararr JSON NOT NULL COMMENT "元素为char类型的json数组"
);
-- 插入数据
INSERT INTO 
    test (jchararr) 
VALUES 
    ('["1","2","3"]'),
    ('["1"]'),
    ('[]'),
    ('["4","2","3"]');
2. 为jchararr 字段中的每个元素创建索引
 
接下来将展示两种不同的方式。
2.1 方式1
2.1.1 创建索引
ALTER Table test ADD INDEX jchararr_index(
     /* 由于数组中的元素类型,sql不知道,需要手动指定数组中的元素的类型为Char*/
    ( CAST(`jchararr` as CHAR(32) ARRAY) )
);
2.1.2 触发索引的查询方式
SELECT * FROM test WHERE '2' MEMBER OF(jchararr);
2.2.3 性能分析
EXPLAIN SELECT * FROM test WHERE '2' MEMBER OF(jchararr);
运行结果:
 
2.1.4 【方式1】的局限性
只适用于当字段的数据为
[1,2,3,4,4]或者['a','b','c']的json数组,而若是[{"id": 1},{"d": 2'}]这样的数据,需创建id的索引,并不支持,因为仅通过CAST(jchararr as CHAR(32) ARRAY)是无法让mysql知道[{"id": 1},{"d": 2'}]中有id这个成员和它的数据类型。当然方式2可以通过$[*].member_namejson内部成员访问符,进行指定,从而解决该问题。
2.2 方式2
2.2.1 创建语句
ALTER Table test ADD INDEX jchararr_index_2(
     /* 由于数组中的元素类型,sql不知道,需要手动指定数组中的元素的类型为Char*/
    ( CAST(`jchararr`->'$[*]' as CHAR(32) ARRAY) )
);
上述的
$[*]'代表json数组中的所有元素,若元素类型为json对象,如:[{"id": 1},{"d": 2'}],则需改成$[*].id。
2.2.2 触发索引的查询方式
SELECT * FROM test WHERE '2' MEMBER OF(jchararr->'$[*]');
上述的
$[*]'代表json数组中的所有元素,若元素类型为json对象,如:[{"id": 1},{"d": 2'}],则需改成$[*].id。
2.2.3 性能分析
EXPLAIN SELECT * FROM test WHERE '2' MEMBER OF(jchararr->'$[*]');
运行结果:
 



















