如何让json里面的value支持索引范围检索

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

标签

PostgreSQL , json , 索引 , gin , btree_gin , 范围检索 , 表达式索引


背景

JSON,JSONB是PG从9就开始引入的数据类型,开发人员非常喜欢,对于JSON里面的内容的检索,我们可以使用GIN索引,目前直接对JSON字段创建GIN索引,可以支持任意PATH的等值、包含检索。

https://www.postgresql.org/docs/10/static/datatype-json.html#JSON-INDEXING

但是,在多数场景中,我们可能还需要范围检索的需求,例如消费范围,年龄范围,收入范围等等。

使用表达式组合索引,很好的满足需求。

例子

单KEY,直接用btree索引

postgres=# create table test (id int, js jsonb);  
CREATE TABLE  
postgres=# create index idx_test_2 on test using btree (((js->>'key1')::int));  
CREATE INDEX  
postgres=# explain select * from test where (js->>'key1')::int between 1 and 10 ;  
                                              QUERY PLAN                                                
------------------------------------------------------------------------------------------------------  
 Index Scan using idx_test_2 on test  (cost=0.15..24.27 rows=6 width=36)  
   Index Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10))  
(2 rows)  

多KEY混合,使用btree_gin, 表达式索引

例如需要查询key1,key2,key3的任意组合范围查询。

postgres=# create extension btree_gin;  
CREATE EXTENSION  
postgres=# create index idx_test_1 on test using gin (((js->>'key1')::int), ((js->>'key2')::int), ((js->>'key3')::int));  
CREATE INDEX  
postgres=# explain select * from test where (js->>'key1')::int between 1 and 10   
postgres-# ;  
                                                 QUERY PLAN                                                   
------------------------------------------------------------------------------------------------------------  
 Bitmap Heap Scan on test  (cost=24.07..33.64 rows=6 width=36)  
   Recheck Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10))  
   ->  Bitmap Index Scan on idx_test_1  (cost=0.00..24.06 rows=6 width=0)  
         Index Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10))  
(4 rows)  
postgres=# explain select * from test where (js->>'key1')::int between 1 and 10  or (js->>'key2')::int between 1 and 15;  
                                                                                             QUERY PLAN                                                                                               
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  
 Bitmap Heap Scan on test  (cost=48.13..59.32 rows=13 width=36)  
   Recheck Cond: (((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10)) OR ((((js ->> 'key2'::text))::integer >= 1) AND (((js ->> 'key2'::text))::integer <= 15)))  
   ->  BitmapOr  (cost=48.13..48.13 rows=13 width=0)  
         ->  Bitmap Index Scan on idx_test_1  (cost=0.00..24.06 rows=6 width=0)  
               Index Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10))  
         ->  Bitmap Index Scan on idx_test_1  (cost=0.00..24.06 rows=6 width=0)  
               Index Cond: ((((js ->> 'key2'::text))::integer >= 1) AND (((js ->> 'key2'::text))::integer <= 15))  
(7 rows)  
postgres=# explain select * from test where (js->>'key1')::int between 1 and 10  and (js->>'key2')::int between 1 and 15;  
                                                                                             QUERY PLAN                                                                                                
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  
 Bitmap Heap Scan on test  (cost=40.00..44.05 rows=1 width=36)  
   Recheck Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10) AND (((js ->> 'key2'::text))::integer >= 1) AND (((js ->> 'key2'::text))::integer <= 15))  
   ->  Bitmap Index Scan on idx_test_1  (cost=0.00..40.00 rows=1 width=0)  
         Index Cond: ((((js ->> 'key1'::text))::integer >= 1) AND (((js ->> 'key1'::text))::integer <= 10) AND (((js ->> 'key2'::text))::integer >= 1) AND (((js ->> 'key2'::text))::integer <= 15))  
(4 rows)  

参考

https://www.postgresql.org/docs/10/static/datatype-json.html#JSON-INDEXING

https://www.postgresql.org/docs/10/static/btree-gin.html

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
8月前
|
JSON 关系型数据库 MySQL
MySQL全文搜索与JSON支持:高效检索与灵活数据处理
本文深入探讨了MySQL数据库中的全文搜索与JSON支持,通过详细的代码示例,阐述了全文搜索的原理、全文索引的创建,以及JSON数据类型的使用与操作。全文搜索在数据库中的重要性日益凸显,MySQL提供了全文索引来实现高效的文本数据检索,通过MATCH AGAINST语句,可以轻松地进行全文搜索操作。此外,MySQL的JSON支持为半结构化数据的存储和查询提供了灵活的解决方案,您可以存储JSON对象、数组等数据,并使用JSON函数来查询和修改数据。
392 0
|
JSON 数据库 数据格式
将json原型 key value保存数据库并且取出
将json原型 key value保存数据库并且取出
|
SQL XML JSON
MySQL请求使用JSON索引查询数据量不准确
MySQL请求使用JSON索引查询数据量不准确
|
JSON JavaScript 数据格式
VUE element-ui之jspreadsheet-ce在线表格数据json序列化(excel数据同步为相应key:value,并过滤掉为空的数据,未输入的行)
VUE element-ui之jspreadsheet-ce在线表格数据json序列化(excel数据同步为相应key:value,并过滤掉为空的数据,未输入的行)
467 0
VUE element-ui之jspreadsheet-ce在线表格数据json序列化(excel数据同步为相应key:value,并过滤掉为空的数据,未输入的行)
|
JSON JavaScript 数据格式
js替换两个数组对象(json)中指定的key:value(键值对中的value)
js替换两个数组对象(json)中指定的key:value(键值对中的value)
1286 0
js替换两个数组对象(json)中指定的key:value(键值对中的value)
|
SQL JSON 关系型数据库
MySQL 8.0.21 JSON_VALUE() 介绍
MySQL 8.0.21发布了,其中一个新特性是JSON_VALUE()函数。主要的动机是简化JSON数据的索引创建,但是还有更多的原因。
1824 0
|
JSON fastjson 数据格式
根据json的key获取到对应的value
根据json的key获取到对应的value
885 0
|
JSON 测试技术 数据格式