首页 > 数据库 >MySQL8.0 JSON的对比、排序和索引

MySQL8.0 JSON的对比、排序和索引

时间:2023-08-16 15:02:03浏览次数:47  
标签:name -- 索引 JSON MySQL8.0 类型 NULL id

(目录)

JSON的对比和排序

JSON值可以通过=, <, <=, >, >=, <>, !=, <=>操作符来进行对比 JSON不支持BETWEEN,IN(),GREATEST(),LEAST(),可以通过将JSON转换为其他数据类型来使用这些操作符。

JSON值的对比在两个级别上进行,先进行数据类型的对比,如果类型相同,再进行值的对比。类型可以通过JSON_TYPE()函数来进行获取。

JSON值类型优先级

MySQL不支持在ORDER BYGROUP BY中对JSON数组和对象进行排序,所以如果在查询语句中执行ORDER BYGROUP BY,其中数组和对象的顺序可能与下述不同

JSON值的类型优先级:

-- 由上到下由大到小
BLOB
BIT
OPAQUE
DATETIME
TIME
DATE
BOOLEAN
ARRAY
OBJECT
STRING
INTEGER, DOUBLE
NULL

同类型的JSON值的顺序

任意JSON值与NULL值对比,结果为UNKNOWN 对于同种类型的JSON值,对比规则如下:

  • BLOB,BIT,OPAQUE 对比前N个字符,如果前N个字符相同,长度短的值更小 .N等于较短值的长度。
  • ARRAY 如果两个JSON数组具有相同的长度,并且数组中相应位置的值相等,则它们相等。 如果数组不相等,则它们的顺序由第一个位置上存在差异的元素决定。该位置的值较小的数组较大。 如果较短数组的所有值都等于较长数组中的相应值,则优先排序较短数组。
-- 数组对比示例
[] < ["a"] < ["ab"] < ["ab", "cd", "ef"] < ["ab", "ef"]
-- JSON不支持在order by和group by中对数组进行对比和排序,所以如过在查询中使用order by,结果可能与上述结果不同
-- 例如以下语句, ["ab", "cd", "ef"] < ["ab", "ef"],但是结果中顺序相反
mysql> select value from test_json where json_type(value)="ARRAY" order by value ;
+--------------------+
| value              |
+--------------------+
| []                 |
| ["a"]              |
| ["ab"]             |
| ["ab", "ef"]       | 
| ["ab", "cd", "ef"] |
+--------------------+
  • BOOLEAN false < true
  • OBJECT 如果两个对象具有相同的键,并且每个键的值相等,那么两个JSON对象相等。不区分键值对在对象中出现的顺序 {"a": 1, "b": 2} = {"b": 2, "a": 1}
  • STRING 使用utf8mb4字符集和utf8mb4_bin排序规则,区分大小写 "A" <"a" < "ab" < "b" < "bc"
  • INTEGER, DOUBLE JSON值可以包含精确值和近似值。在JSON值中的数值比较与MySQL数值类型不同
    • 在对比MySQL的INT和DOUBLE类型时,将int转换为double来进行对比
    • 在对比JSON的数值时,无法确定数值是整数还是浮点数,MySQL会将浮点数转换为整数。排序结果不会失去精确值的数组精度。 9223372036854775805 < 9223372036854775806 < 9223372036854775807 < 9.223372036854776e18 = 9223372036854776000 < 9223372036854776001

JSON和非JSON的转换

其他类型 CAST(其他类型 AS JSON) CAST(JSON AS 其他类型)
utf8字符类型(utf8mb4,utf8mb3,ascii) 将字符串解析为JSON 将JSON转换为utf8mb4字符串
其他字符类型 先转换为utf8mb4字符类型再解析为JSON JSON转换为utf8mb4字符串,然后转换为其他字符类型
NULL 返回JSON类型的NULL值 不适用
几何类型 通过调用ST_AsGeoJSON()来转换为JSON文档 不能这样操作,可以使用ST_GeomFromGeoJSON( CAST(json_val AS CHAR))来将JSON转换为几何类型
其他类型 返回一个包含JSON标量的JSON文档 如果JSON文档包含目标类型的单个标量值,并且该标量值可以强制转换为目标类型,则成功。否则,返回NULL并产生警告

JSON的索引

不能直接在JSON列上创建索引,要优化对JSON列的查询,可以在生成列上创建索引

注意:如果要在字符串值上创建索引,建议在创建生成列时使用以下方法

doc_name TEXT AS (JSON_UNQUOTE(JSON_EXTRACT(jdoc, '$.name'))) STORED
-- (JSON_UNQUOTE(JSON_EXTRACT(jdoc, '$.name'))) 等同于 (jdoc->>"$.name")

存疑:在官方文档Optimizer Use of Generated Column Indexes中表示

  • 生成列定义时使用c->>"$.name"并在该列上创建索引 可以为c->>"$.name"c->"$.name"进行优化,
  • 生成列定义时使用c->"$.name"并在该列上创建索引 仅能为c->"$.name"进行优化。

但是实际测试中没有使用到c->"$.name"的生成列索引,建议使用c->>"$.name"的形式创建生成列和索引。

示例

-- 建表
mysql> CREATE TABLE jemp (
    ->     id int auto_increment primary key,
    ->     c JSON,
    ->     g INT GENERATED ALWAYS AS (c->"$.id"),
    ->     n varchar(200) GENERATED ALWAYS AS (c->>"$.name"),
    ->     n2 varchar(200) GENERATED ALWAYS AS (c->"$.name"),
    ->     index g(g),
    ->     index n (n),
    ->     index n2(n2)
    -> );

-- 插入数据
mysql> INSERT INTO jemp (c) VALUES ('{"id": "1", "name": "Fred"}'), ('{"id": "2", "name": "Wilma"}'),('{"id": "3", "name": "Barney"}'), ('{"id": "4", "name": "Betty"}');

-- 检查数据
mysql> select * from jemp;
+----+-------------------------------+------+--------+----------+
| id | c                             | g    | n      | n2       |
+----+-------------------------------+------+--------+----------+
|  1 | {"id": "1", "name": "Fred"}   |    1 | Fred   | "Fred"   |
|  2 | {"id": "2", "name": "Wilma"}  |    2 | Wilma  | "Wilma"  |
|  3 | {"id": "3", "name": "Barney"} |    3 | Barney | "Barney" |
|  4 | {"id": "4", "name": "Betty"}  |    4 | Betty  | "Betty"  |
+----+-------------------------------+------+--------+----------+

-- 查看执行计划
mysql> explain select * from jemp where c->"$.id" >2;
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | jemp  | NULL       | range | g             | g    | 5       | NULL |    2 |   100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

-- 查询c->"$.name",只用到了n列作为索引,n列定义:n varchar(200) GENERATED ALWAYS AS (c->>"$.name")
mysql> explain select * from jemp where c->"$.name" ="Barney";
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | jemp  | NULL       | ref  | n             | n    | 803     | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

-- 查询c-->"$.name",也只用到了n列作为索引,n列定义:n varchar(200) GENERATED ALWAYS AS (c->>"$.name")
mysql> explain select * from jemp where c->>"$.name" ="Barney";
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | jemp  | NULL       | ref  | n             | n    | 803     | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

标签:name,--,索引,JSON,MySQL8.0,类型,NULL,id
From: https://blog.51cto.com/yueyinsha/7108321

相关文章

  • C#实现用正则表达式替换JSON中大字段的内容
    ///<summary>///过长的数据在日志中不显示///</summary>///<paramname="orilog">原请求</param>///<paramname="ignore">需要过滤的参数</param>privatestringRemoveIgnor......
  • C# Json 序列化 反序列化
    ///<summary>///Json编码器///</summary>///<typeparamname="T"></typeparam>publicclassJsonEncode{///<summary>///反序列化///</summary>///<paramname="data"></param&g......
  • m扩展索引OFDM(Spread-OFDM-IM)matlab仿真,信号检测对比ZF,MMSE,ML等方法
    1.算法仿真效果matlab2022a仿真结果如下:     2.算法涉及理论知识概要        基于索引调制的OFDM(OFDM-IM,OFDMwithIndexModulation)技术被提出,在频率选择性衰落信道上提升了系统的分集增益,特别是在较低频谱效率场景下能够有效降低系统的误比特率。......
  • @JsonComponent注解自定义JSON序列化与反序列化
    1.概述本篇教程将聚焦于如何使用SpringBoot中的@JsonComponent通过使用这个注解,我们不需要手动引用ObjectMapper对象就可以将一个类暴露为Jackson的serializer与deserializer。由于这是SpringBoot提供的功能,所以我们不需要添加额外的依赖,我们可以直接在SpringBoot程序中使用它......
  • 在Angular项目中如何读取json文件呢?
    直接进入主题,我们的最终目得是要读取文件,那么首先我们需要先创建文件,第一步:创建我们今天所需要在assets创建需要读取的文件Message.json,如下:[{"id":"E0001","msg":"{0}の取得に失敗しました。"},{"id":"E0002",&quo......
  • Asp.net WebAPI中Controller的方法在接受到json时序列化都为null的问题
    原因是,webapi默认不序列化字段,只序列化属性只需要把字段改成属性即可 ------------------改成---------------- ......
  • 聚簇索引和非聚簇索引区别
    聚簇索引和非聚簇索引是数据库索引的两种主要类型,它们在物理存储和查找数据的方式上有所不同。下面是对两者的详细介绍:聚簇索引(ClusteredIndex)物理排序:聚簇索引决定了表中数据行的物理排序。因为数据行与索引的排序方式是相同的,所以一个表只能有一个聚簇......
  • 动态HTTP代理与搜索引擎优化(SEO)的关系
     作为一名专业的爬虫代理供应者,今天我要和大家聊一聊动态HTTP代理与搜索引擎优化(SEO)之间的关系。你可能会觉得这两个话题没有直接联系,但实际上它们是息息相关的。在这篇文章中,我将向大家解释为什么使用动态HTTP代理对于提升网站的SEO效果至关重要,并分享一些实用的技巧。 首先......
  • fastjson反序列化 TODO
    参考链接fastjson反序列化入门文章https://tttang.com/archive/1579/https://xz.aliyun.com/t/12096ASM动态加载相关,如何查看内存生成的类的源码https://juejin.cn/post/6974566732224528392#heading-6https://blog.csdn.net/wjy160925/article/details/85288569关闭ASM去......
  • MySQL的空间索引
    空间索引是一种特殊的数据库索引,用于存储空间数据并加速空间查询。空间数据通常是指与地理位置或空间坐标有关的数据,如经度和纬度、多边形边界、点等。空间索引的目的是快速查找在特定地理区域内或与特定地理形状相交的对象。以下是空间索引的一些核心概念和特点......