MySQL 允许你在 JSON 数据上创建索引
测试用例
代码语言:sql复制CREATE TABLE `student` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int DEFAULT NULL,
`courses` json DEFAULT NULL,
`address` json DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
INSERT INTO student (name, age, courses, address) VALUES
('张伟', 20, '[{"credits": 3.0, "course_id": "CS101", "course_name": "计算机基础"}, {"credits": 4.0, "course_id": "MATH202", "course_name": "高等数学"}]', '{"zip": "100000", "city": "北京", "state": "北京市", "street": "北京市朝阳区幸福路123号"}'),
('李娜', 22, '[{"credits": 3.0, "course_id": "BIO301", "course_name": "生物学基础"}]', '{"zip": "200000", "city": "上海", "state": "上海市", "street": "上海市浦东新区花园路456号"}');
mysql> select * from studentG;
*************************** 1. row ***************************
id: 1
name: 张伟
age: 20
courses: [{"credits": 3.0, "course_id": "CS101", "course_name": "计算机基础"}, {"credits": 4.0, "course_id": "MATH202", "course_name":
"高等数学"}]address: {"zip": "100000", "city": "北京", "state": "北京市", "street": "北京市朝阳区幸福路123号"}
*************************** 2. row ***************************
id: 2
name: 李娜
age: 22
courses: [{"credits": 3.0, "course_id": "BIO301", "course_name": "生物学基础"}]
address: {"zip": "200000", "city": "上海", "state": "上海市", "street": "上海市浦东新区花园路456号"}
2 rows in set (0.00 sec)
需求:
在student表的courses字段中,为JSON数据内的course_id键创建索引。
-- 创建函数索引
ALTER TABLE student
ADD INDEX idx_course_id ((CAST(courses->'$[*].course_id' AS CHAR(50) ARRAY)));
代码语言:sql复制mysql> -- 可以看到已经用到索引
mysql> EXPLAIN SELECT * FROM student
-> WHERE JSON_CONTAINS(courses->'$[*].course_id', '"CS101"')G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
partitions: NULL
type: range
possible_keys: idx_course_id
key: idx_course_id
key_len: 203
ref: NULL
rows: 1
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
上述的方式是通过MySQL 8.0 创建函数索引解决。
那么 MySQL 5.7 如何在 JSON 数据上创建索引?
答:使用虚拟列 全文索引:
代码语言:sql复制-- 添加一个虚拟列
ALTER TABLE student
ADD COLUMN course_ids varchar(50) GENERATED ALWAYS AS
(CONCAT_WS(' ', JSON_UNQUOTE(JSON_EXTRACT(courses, '$[*].course_id')))) STORED;
代码语言:sql复制-- 创建全文索引
ALTER TABLE student
ADD FULLTEXT INDEX idx_course_ids (course_ids) WITH PARSER ngram;
代码语言:sql复制mysql> -- 使用全文搜索
mysql> EXPLAIN SELECT * FROM student
-> WHERE MATCH(course_ids) AGAINST ('CS101' IN BOOLEAN MODE)G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: student
partitions: NULL
type: fulltext
possible_keys: idx_course_ids
key: idx_course_ids
key_len: 0
ref: const
rows: 1
filtered: 100.00
Extra: Using where; Ft_hints: no_ranking
1 row in set, 1 warning (0.00 sec)
结论
JSON 数据类型是在 MySQL 中存储 JSON 数据的好方法。 它提供验证功能,允许创建索引,并使用 JSON 函数操作 JSON 数据。 它是 TEXT 数据类型的最佳替代品。