MySQL JSON单字段和多字段(集合)索引创建和使用

位置:首页>文章>详情   分类: 教程分享   阅读(0)   2024-04-10 11:03:21

MySQL,从大概5.7版本开始支持json数据类型,但是5.7的json查询不支持创建索引,在MySQL 8.0.17 后支持了索引,但是创建和查询使用索引与常规索引不同,一般的数据库工具如navcate没法看到

环境

确保当前MySQL版本大于8.0.17 低于这个版本JSON多值索引无法创建无需折腾,不支持。单字段(属性)通过虚拟列也至少需要MySQL5.7+

MySQL json索引创建

 

JSON 数组 (多值索引,索引值为数组)

MySQL 表字段为json,json字段内容是个json数组,MySQL version 8.0.17 +

json数组字段,也就是表中存的数据类型为json,数据就是一个数组,如

DROP TABLE IF EXISTS `student`;
CREATE TABLE student(
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    book_ids json NOT NULL comment '测试json字段'
);

插入测试数据

INSERT INTO student (book_ids) VALUES ('[1,2,3]');
INSERT INTO student (book_ids) VALUES ('[2,3,5]');
INSERT INTO student (book_ids) VALUES ('[6,9,10]');
INSERT INTO student (book_ids) VALUES ('[-1,20]');

 

未添加索引,查询语句尝试:

查询
查询

观察,可以看到此时json数据查询并未走索引。接下来创建json数组的索引

ALTER Table `student` 
ADD INDEX idx_bookIds
(
    (CAST( `book_ids` -> "$[*]"  as CHAR(32)  ARRAY))
);

操作示例图-76b3d3c2296c4e9ba54e05c916aac9bf.png

 

再次查询和检查索引情况

操作示例图-a3bbb5f15a01494bb711f3d12c2e2310.png

此时可以看到查询已经走索引了,上方使用到了JSON_CONTAINS 函数

提示:

  • 目前MySQL 8  只支持MEMBER OFJSON_CONTAINS,JSON_OVERLAB 三个函数可以使用到多值索引。
  • 索引不支持用于表关联
  • 不能结合前缀索引
  • 不支持排序
  • 字符集utf8mb4字符集的排序规则必须是utf8mb4_0900_as_cs
  •  binary字符集的排序规则必须是binary

三个函数使用参考:

select * from student where JSON_CONTAINS(book_ids ->'$[*]','-1');

select * from student where -1 MEMBER OF(book_ids ->'$[*]');

select * from student where JSON_OVERLAPS(book_ids ->'$[*]',CAST('[1,-1]' AS JSON));

特别注意,JSON_CONTAINS(book_ids ->'$[*]','-1');如果参数不是数据库中的字段的话,一定要加引号,就算是整型也得加

对于已知值得情况下,使用MEMBER OF 效率高于JSON_CONTAINS JSON_CONTAINS第二个参数可以是指定值或者数据库中字段由于需要解析所以效率比MEMBER OF略低

JSON_OVERLAPS 函数解释参考:MySQL JSON_OVERLAPS() 函数使用指南 (sjkjc.com)

 

 

创建表时候添加json数组索引参考:

DROP TABLE IF EXISTS `student`;
CREATE TABLE student(
        id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        book_ids json NOT NULL comment '测试json字段',
        index idx_json_tenantIds((CAST(`book_ids` -> "$[*]" AS CHAR(32) ARRAY)))
);

 

注意!

需要注意,查询语句必须是JSON_CONTAINS(book_ids -> '$[*]','-1')  如果是JSON_CONTAINS(book_ids, '-1')  同样不会走索引,参考

创建多值索引语法:

ALTER TABLE your_table_name ADD INDEX idx_json_your_index_name( ( CAST( your_table_json_column_name -> '$.json_key' AS [TYPE] [array] ) ) ); 

注意意:这里在CAST语法外面有两层单括号!,如果少写一个会报错!

[TYPE]的取值为:DATE,DATEYIME,DECIMAL,DOUBLE,FLOAT,SIGNED,TIME,UNSIGNED,YEAR 

同时支持唯一索引:

ALTER TABLE your_table_name ADD UNIQUE INDEX idx_json_your_index_name( ( CAST( your_table_json_column_name -> '$.json_key' AS [TYPE] [array] ) ) ); 

提示:在创建唯一索引时,需要保证没有重复数据,否则会报错。同样,创建唯一索引之后,如果插入重复数据也会报错。

操作示例图-fba3f88c7a6649e7bb8103d86086703c.png

可以看到数据虽然同样能查询出来,但是没有走索引

 

JSON对象单字段/属性索引

MySQL 表字段为json类型,json字段存储为json对象的内容,通过虚拟列+对虚拟列创建普通索引实现 MySQL version 5.7+

示例表设计和数据:

DROP TABLE IF EXISTS `student`;
CREATE TABLE student(
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    book json NOT NULL comment '测试json字段'
);

插入测试数据

INSERT INTO student (`book`) VALUES ('{"id":1,"name":"书1"}');
INSERT INTO student (`book`) VALUES ('{"id":2,"name":"书2"}');
INSERT INTO student (`book`) VALUES ('{"id":3,"name":"书3"}');
INSERT INTO student (`book`) VALUES ('{"id":4,"name":"书4"}');

 

未添加索引,查询书id大于2的数据尝试:

EXPLAIN
SELECT * FROM student WHERE book->'$.id' > 2;

查询,无索引

观察,可以看到此时json数据查询并未走索引。接下来创建json对象的属性索引

ALTER TABLE `student` 
    ADD COLUMN `book_id` BIGINT 
        GENERATED ALWAYS AS (json_extract(`book`, '$.id')) VIRTUAL, 
ADD INDEX idx_json_bookId(`book_id`);

上面两句sql解释:

  1. 修改表添加一个虚拟字段,来源json字段的某个属性
  2. 对前面虚拟列增加一个普通索引

提示:虚拟列不需要维护,会根据json属性值自动更新

添加索引后执行查询和观察索引使用情况:

json索引查询

观察可以看到查询使用到了索引,且表多了一列

 

地址:https://www.leftso.com/article/mysql8-json-index.html

相关阅读

MySQL,从大概5.7版本开始支持json数据类型,但是5.7的json查询不支持创建索引,在MySQL 8.0.17 后支持了索引,但是创建和查询使用索引与常规索引不同
环境说明1.MySQL5.7(注意,json格式最低需要改版本支持);2.存json数据的数据库字段类型必须是json,不能是varchar;
java json字符串转对象_json转换为java对象_ json字符串转对象数组
说明:json除了键值对的形式以外,还包括Array数列形式,这在mysql5.7及以上也是支持的,对Array中元素的操作相当于直接对键值对中的值操作,少了“键”的定位这一步,这里不单独展示,...
使用Jackson写巨大的JSON文件
MySQL索引优化,MySQL索引类型,MySQL索引怎么用MySQL索引怎么创建这里将会通过一些简单得sql进行讲解
mysql索引的使用基础知识摘录。
Java EE 8 JSON Pointer讲解,Java EE 8包含JSON处理API的更新,并为最新的JSON标准提供最新的IEFT标准。
handlerexceptionresolver 返回json
Form前置准备首先我们有一个表单<form id="params"&gtl; <input name="userName" value="123"&gtl; <...