前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL如何给JSON列添加索引(二)

MySQL如何给JSON列添加索引(二)

作者头像
SEian.G
发布2021-07-07 15:01:02
7.3K0
发布2021-07-07 15:01:02
举报
文章被收录于专栏:SEian.G学习记录

上一篇文章《MySQL 8.0 JSON增强到底有多强?(一)》,我们简单介绍了MySQL中JSON数据类型,相信大家对JSON数据类型有了一定的了解,那么今天我们来简单看下如何在JSON列上添加索引?

InnoDB支持虚拟生成列的二级索引。不支持其他索引类型。在虚拟列上定义的二级索引有时称为“虚拟索引”。

二级索引可以在一个或多个虚拟列上创建,也可以在虚拟列和常规列或存储的生成列的组合上创建。包含虚拟列的二级索引可以定义为UNIQUE。

在虚拟生成的列上创建辅助索引时,生成的列值将在索引的记录中具体化。如果索引是覆盖索引(包含查询检索到的所有列的索引),则从索引结构中的物化值检索生成的列值,而不是“动态”计算。

在虚拟列上使用二级索引时,由于在操作期间INSERT和 UPDATE操作期间在二级索引记录中实现虚拟列值时要执行计算,因此要考虑额外的写入成本。即使有额外的写入成本,虚拟列上的二级索引也可能比生成的存储列更好,后者在聚簇索引中实现,从而导致需要更多磁盘空间和内存的较大表。如果未在虚拟列上定义二级索引,则读取会产生额外成本,因为每次检查列的行时都必须计算虚拟列值。

对索引的虚拟列的值进行MVCC记录,以避免在回滚或清除操作期间对生成的列值进行不必要的重新计算。对于 COMPACT和REDUNDANT格式,记录值的数据长度受索引键限制767字节,对于DYNAMIC和 COMPRESSED列格式,受索引键限制3072字节。

在虚拟列上添加或删除二级索引是就地操作。

通过索引生成列以提供JSON列索引

JSON 不能直接对列进行索引。要创建间接引用此类列的索引,可以定义一个生成列,该列提取应建立索引的信息,然后在生成的列上创建索引,如下所示:

说明:8.0和5.7都支持在生成列上添加索引

代码语言:javascript
复制
mysql>CREATE TABLE jemp (
    ->     c JSON,
    ->     g INT GENERATED ALWAYS AS (c->"$.id"),
    ->     INDEX i (g)
    -> );
Query OK, 0 rows affected (0.01 sec)
 
查看表结构:
 
8.0表结构:
mysql >show create table jemp\G
*************************** 1. row ***************************
       Table: jemp
Create Table: CREATE TABLE `jemp` (
  `c` json DEFAULT NULL,
  `g` int GENERATED ALWAYS AS (json_extract(`c`,_utf8mb3'$.id')) VIRTUAL,
  KEY `i` (`g`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
 
5.7表结构:
mysql>show create table jemp\G
*************************** 1. row ***************************
       Table: jemp
Create Table: CREATE TABLE `jemp` (
  `c` json DEFAULT NULL,
  `g` int(11) GENERATED ALWAYS AS (json_extract(`c`,'$.id')) VIRTUAL,
  KEY `i` (`g`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
 
mysql >INSERT INTO jemp (c) VALUES
    -> ('{"id": "1", "name": "Fred"}'), ('{"id": "2", "name": "Wilma"}'),
    -> ('{"id": "3", "name": "Barney"}'), ('{"id": "4", "name": "Betty"}');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0
 
 
mysql >select * from jemp;
+-------------------------------+------+
| c                             | g    |
+-------------------------------+------+
| {"id": "1", "name": "Fred"}   |    1 |
| {"id": "2", "name": "Wilma"}  |    2 |
| {"id": "3", "name": "Barney"} |    3 |
| {"id": "4", "name": "Betty"}  |    4 |
+-------------------------------+------+
4 rows in set (0.00 sec)
 
 
mysql >SELECT c->>"$.name" AS name FROM jemp WHERE g > 2;
+--------+
| name   |
+--------+
| Barney |
| Betty  |
+--------+
2 rows in set (0.00 sec)
 
查看执行计划:
mysql >EXPLAIN SELECT c->>"$.name" AS name FROM jemp WHERE g > 2\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: jemp
   partitions: NULL
         type: range
possible_keys: i
          key: i
      key_len: 5
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

通过上述查看执行计划,可以看到使用到了我们在生成列上创建的索引;

当EXPLAIN在SELECT包含一个或多个使用->or->> 运算符的一个 或其他SQL语句上使用时 ,这些表达式将使用JSON_EXTRACT()和(如果需要)转换为它们的等效项JSON_UNQUOTE(),如SHOW WARNINGS输出所示:

代码语言:javascript
复制
mysql>EXPLAIN SELECT c->>"$.name" FROM jemp WHERE g > 2 ORDER BY c->"$.name"\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: jemp
   partitions: NULL
         type: range
possible_keys: i
          key: i
      key_len: 5
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: Using where; Using filesort
1 row in set, 1 warning (0.00 sec)
 
mysql >SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select json_unquote(json_extract(`wjqdb`.`jemp`.`c`,'$.name')) AS `c->>"$.name"` from `wjqdb`.`jemp` where (`wjqdb`.`jemp`.`g` > 2) order by json_extract(`wjqdb`.`jemp`.`c`,'$.name')
1 row in set (0.00 sec)

在MySQL 8.0.21和更高版本中,还可以JSON使用JSON_VALUE()带有表达式的函数在列上创建索引,该表达式可用于优化使用该表达式的查询;

后面文章我们会介绍如何在 JSON数组上创建索引以及JSON数据类型涉及到的函数等,敬请期待。。。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA的辛酸事儿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 通过索引生成列以提供JSON列索引
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档