MySQL JSON查询与索引

目录

前言

  • 自MySQL 5.7.8开始引入原生JSON支持,可用于存储动态的列。此时如果想要建立索引,要先建立JSON某一列的虚拟列,使用虚拟列查询。从MySQL 8.0.17开始,InnoDB支持多值索引,相比老版本的查询方式就更直接了。

准备

  • 创建一张配置表,建表语句如下。
shell 复制代码
CREATE TABLE `t_config` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `extras` json DEFAULT NULL COMMENT '扩展列json字段',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='配置表';
  • 测试数据
shell 复制代码
INSERT INTO `t_config` (`id`, `extras`) VALUES (1, '{\"color\": \"red\", \"phone\": [\"157\", \"153\"]}');
INSERT INTO `t_config` (`id`, `extras`) VALUES (2, '{\"color\": \"green\", \"phone\": [\"157\", \"154\"]}');
  • 下面就开始介绍虚拟列多值索引查询与索引方式。

虚拟列

  • 测试平台5.7.26

  • 查询

shell 复制代码
SELECT * FROM `t_config` WHERE extras->'$.color' = 'red';
或
SELECT * FROM `t_config` WHERE json_contains(extras->'$.color','"red"');
  • 现在是走全表扫描

  • 下面创建虚拟列和索引

shell 复制代码
ALTER TABLE `t_config`
ADD COLUMN `v_color` VARCHAR(32) GENERATED ALWAYS AS
(JSON_UNQUOTE(JSON_EXTRACT(`extras`, _utf8mb4'$.color'))) VIRTUAL NULL;

CREATE INDEX idx_v_color on t_config(v_color);
  • 查询就能走索引了
shell 复制代码
EXPLAIN SELECT * FROM `t_config` WHERE v_color = 'red';
  • 但是数组phone未找到合适的方式查询。

多值索引

  • 测试平台8.0.43

  • 查询(第二条语句不能利用索引)

shell 复制代码
SELECT * FROM `t_config` WHERE json_contains(extras->'$.color','"red"');
 或者
SELECT * FROM `t_config` WHERE extras->'$.color' = 'red';  
  • 当前是全表扫描
shell 复制代码
EXPLAIN SELECT * FROM `t_config` WHERE json_contains(extras->'$.color','"red"');
  • 增加json里 color字段索引
shell 复制代码
alter table t_config add index json_color( (cast(extras->'$.color' as char(32) array)));
  • 现在就能走索引了

  • 对于数字数组字段,查询方式

  • 要先创建索引,才能查到数据

shell 复制代码
alter table t_config add index phone( (cast(extras->'$.phone' as unsigned array)) );
shell 复制代码
 -- 查询phone字段
 SELECT * FROM `t_config` WHERE json_contains(extras->'$.phone' , '157');

-- 查询phone字段, 参数数组
 SELECT * FROM `t_config` WHERE json_contains(extras->'$.phone' , CAST('[157,153]' AS JSON));
  • 能走索引

总结

  • 从执行计划看,虚拟列的索引执行计划更优,但利用多值索引的json_contains查询方式就不需要转换SQL。
  • 数组列:虚拟列暂未找到查询数组的方式。多值索引要先创建才能查到数据。

参考

相关推荐
摇滚侠2 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
ApacheSeaTunnel4 小时前
实战演示 | 基于 Apache SeaTunnel 与 Apache DolphinScheduler 实现 MySQL 到 Doris 离线定时增量同步
大数据·mysql·开源·doris·数据集成·seatunnel·数据同步
DARLING Zero two♡4 小时前
【MySQL数据库】数据类型与表约束
数据库·mysql
活宝小娜5 小时前
mysql详细安装教程
数据库·mysql·adb
Database_Cool_6 小时前
什么是数据仓库物化视图?AnalyticDB MySQL 实时物化视图能力解析
人工智能·mysql·阿里云
Database_Cool_6 小时前
即席查询(Ad-Hoc)数据库选型:AnalyticDB MySQL 秒级 Ad-Hoc 分析方案
数据库·mysql
一杯奶茶¥6 小时前
水果销售网站 CRM客户信息管理系统 超市管理系 酒店管理系统 健身房管理系统 在线音乐网站 校园招聘系统
java·vue.js·spring boot·mysql·spring·java项目
用户800391387837 小时前
使用 Gemini 解决 MySQL 常见问题
mysql
Database_Cool_7 小时前
什么是湖仓一体?和数据仓库的本质区别(附 AnalyticDB MySQL 湖仓一体方案)
数据库·数据仓库·mysql
XZ-0700019 小时前
MySQL事务
数据库·mysql·oracle