PostgreSQL SRF (set-returning functions) 函数where, index实现
标签
PostgreSQL , set-returning functions , SRF , 索引 , 转换
背景
PostgreSQL 函数支持返回多行,定义returns setof type即可。PG内部也内置了蛮多这样的函数,例如
select proname from pg_proc where proretset; generate_series
unnest json_array_elements json_array_elements_text json_object_keys json_each json_each_text json_to_recordset unnest ts_stat ts_stat ts_token_type ts_token_type ts_parse ts_parse jsonb_array_elements jsonb_array_elements_text jsonb_object_keys jsonb_each jsonb_each_text jsonb_populate_recordset jsonb_to_recordset
............
自定义SRF方法如下:
https://www.postgresql.org/docs/11/static/plpgsql-control-structures.html
对于返回多行的函数,如果在where条件中执行过滤,会返回如下错误。
ERROR: 0A000: set-returning functions are not allowed in WHERE
如果要创建基于SRF函数的表达式索引,会报如下错误:
ERROR: 0A000: set-returning functions are not allowed in index expressions
而实际上,可能在场景中有查询srf = ?这样的需求。
如何达到这样的需求呢?
1、 可以将SRF再转换为ARRAY,然后构建ARRAY的GIN索引。
例如这是个例子 postgres=# create or replace function gen_rand(int,int) returns int[] as $$
select array(select (random()*$1)::int from generate_series(1,$2));
$$ language sql strict;
CREATE FUNCTION postgres=# select gen_rand(100,10); gen_rand
------------------------------- {17,5,33,70,54,10,89,96,5,94}
(1 row)
例子
1、建表
create table a (id int, js jsonb);
2、写入测试数据
postgres=# insert into a select id, jsonb_build_array((random()*1000)::int, (random()*1000)::int,(random()*1000)::int,(random()*1000)::int,(random()*1000)::int,(random()*1000)::int,(random()*1000)::int,(random()*1000)::int,(random()*1000)::int,(random()*1000)::int) from generate_series(1,10000) t(id);
INSERT 0 10000
3、数据样本
postgres=# select * from a limit 2; id | js
----+--------------------------------------------------- 1 | [774, 509, 740, 813, 925, 67, 539, 730, 598, 465] 2 | [232, 153, 119, 895, 962, 501, 998, 609, 10, 410]
(2 rows)
4、某个JSON类型的SRF函数调用如下
postgres=# select jsonb_array_elements(js) from a where id=1; jsonb_array_elements
---------------------- 774 509 740 813 925 67 539 730 598 465
(10 rows)
在WHERE中过滤,创建表达式索引,均报错
postgres=# \set VERBOSITY verbose
postgres=# select * from a where jsonb_array_elements(js) =1;
ERROR: 0A000: set-returning functions are not allowed in WHERE
LINE 1: select * from a where jsonb_array_elements(js) =1; ^
LOCATION: check_srf_call_placement, parse_func.c:2258 postgres=# create index idx_a_1 on a (jsonb_array_elements(js));
ERROR: 0A000: set-returning functions are not allowed in index expressions
LINE 1: create index idx_a_1 on a (jsonb_array_elements(js)); ^
LOCATION: check_srf_call_placement, parse_func.c:2251
5、创建一个UDF,将SRF结果转换为ARRAY
postgres=# create or replace function srf_to_arr(jsonb) returns text[] as $$ select array(select jsonb_array_elements($1)::text);
$$ language sql strict immutable;
CREATE FUNCTION
postgres=# select id,js,srf_to_arr(js) from a limit 1; id | js | srf_to_arr
----+---------------------------------------------------+------------------------------------------ 1 | [774, 509, 740, 813, 925, 67, 539, 730, 598, 465] | {774,509,740,813,925,67,539,730,598,465}
(1 row)
6、WHERE srf = ? 条件变成如下
postgres=# select id,js,srf_to_arr(js) from a where srf_to_arr(js) @> array['1']; id | js | srf_to_arr
------+--------------------------------------------------+----------------------------------------- 18 | [96, 4, 447, 177, 53, 550, 768, 27, 1, 280] | {96,4,447,177,53,550,768,27,1,280} 67 | [402, 1, 841, 834, 462, 769, 247, 568, 114, 690] | {402,1,841,834,462,769,247,568,114,690} 102 | [555, 599, 389, 719, 1, 916, 910, 637, 566, 36] | {555,599,389,719,1,916,910,637,566,36} 162 | [687, 1, 628, 851, 20, 522, 883, 814, 874, 938] | {687,1,628,851,20,522,883,814,874,938}
.....
7、创建表达式索引
postgres=# create index idx_a_1 on a using gin(srf_to_arr(js));
CREATE INDEX
用上了这个GIN倒排索引
postgres=# explain select id,js,srf_to_arr(js) from a where srf_to_arr(js) @> array['1']; QUERY PLAN
----------------------------------------------------------------------- Bitmap Heap Scan on a (cost=3.69..76.70 rows=50 width=160) Recheck Cond: (srf_to_arr(js) @> '{1}'::text[]) -> Bitmap Index Scan on idx_a_1 (cost=0.00..3.67 rows=50 width=0) Index Cond: (srf_to_arr(js) @> '{1}'::text[])
(4 rows)
参考
https://www.postgresql.org/docs/11/static/plpgsql-control-structures.html
PostgreSQL SRF (set-returning functions) 函数where, index实现相关推荐
- PostgreSQL仿照Oracle的instr函数
转自:http://www.myexception.cn/operating-system/480929.html PostgreSQL模仿Oracle的instr函数 -- -- instr fun ...
- Python之pandas:pandas中to_csv()、read_csv()函数的index、index_col(不将索引列写入)参数详解之详细攻略
Python之pandas:pandas中to_csv().read_csv()函数的index.index_col(不将索引列写入)参数详解之详细攻略 目录 pandas中to_csv().read ...
- PostgreSQL学习笔记5之函数和操作符一
一.逻辑操作符: 常用的逻辑操作符有:AND.OR和NOT.其语义与其它编程语言中的逻辑操作符完全相同. 二.比较操作符: 下面是PostgreSQL中提供的比较操作符列表: 操作符 描述 < ...
- PostgreSQL 查询数据库中所有函数信息,函数名(全部)
PostgreSQL 查询数据库中所有函数信息,函数名(全部) selectp .oid,p .proname,p .proargtypes,p .proacl,p .prorettype,p .pr ...
- PostgreSQL学习笔记7之函数和操作符三
九.序列操作函数: 序列对象(也叫序列生成器)都是用CREATE SEQUENCE创建的特殊的单行表.一个序列对象通常用于为行或者表生成唯一的标识符.下面序列函数,为我们从序列对象中获取最新的序列值提 ...
- index match函数的使用方法_必学函数组合INDEX+MATCH,秒杀VLOOKUP函数
VLOOKUP 职场里面用的太频繁的,是必须掌握使用的函数公式,在这个函数的使用过程中,有时候用起来也不是很方便,比如下面两个场景 ❶逆向查找匹配 左边是员工编号,姓名,工资表格数据,现在需要根据姓名 ...
- 计算机函数match,秒杀vlookup函数,Index+Match函数组合
lookup是工作中函数组合. 1.反向查找 [例1]如下图所示,要求根据产品名称,查找编号. 分析: 先利用Match函数根据产品名称在C列查找位置 =MATCH(B13,C5:C10,0) 再用I ...
- python find函数 和index的区别_【全网最简单Python教程】--10.列表元素的索引和返回索引值(Index函数使用)...
在练习日4中,小鱼给大家讲述了神秘的ASCII码编译及解密过程. 在ASCII码中,字符与十进制数字的互相转换是通过 ord()函数和chr()函数. 今天小鱼要给大家介绍另一种在影视剧.侦探小说中更 ...
- PostgreSQL MySQL 兼容性之 - bit 函数和操作符
bit 函数和操作符 MySQL &Bitwise AND <<Left shift >>Shift right BIT_COUNTReturns the number ...
- PostgreSQL学习笔记6之函数和操作符二
六.模式匹配: PostgreSQL中提供了三种实现模式匹配的方法:SQL LIKE操作符,更近一些的SIMILAR TO操作符,和POSIX-风格正则表达式. 1. LIKE: st ...
最新文章
- 解题报告:【kuangbin带你飞】专题四 最短路练习题
- 卓越性能代码_开启win10隐藏的“超级性能模式”
- hdu3987 最小割边数
- 大话ion系列(二)
- 硬件:选购CPU和显卡需了解的参数,TDP、SDP、ACP、GCP、TBP是什么?
- 基于JAVA+SpringBoot+Mybatis+MYSQL的校园兼职招聘系统
- BZOJ 2724: [Violet 6]蒲公英
- java中输出进程的映像名称,怎么修改tomcat进程的名称(windows)
- Android调试wifi使用wpa_supplicant和wpa_cli总结
- sketchup 255个su常用插件)_[插件课堂] SU.KIT发布了v2020,完美支持SketchUp 2020
- vs2015注册密钥
- 蚂蚁课堂学习笔记之springAop和Ioc
- Kolmogorov 的数学观与业绩
- 百度关键词地区排名查询php源码,百度关键词地区排名查询
- 【mysql 练习题】查询和“01”号同学所学课程完全相同的其他同学的学号
- Python 导出微信电子相册中的照片
- outlook企业邮箱服务器怎么填,Outlook客户端怎么配置企业邮箱
- WLC-WLC升级(以2504为例)
- 物质的折射率和光的折射率的关系
- Google大数据三大论文
热门文章
- 警告: A docBase inside the host appBase has been specified, and will be ignore
- 台式计算机电源接线图,​台式机硬盘电源线接法【图解】
- android studio图形验证码,android 一行代码,快速实现图片验证码(附android studio 版小demo)...
- html 小游戏 俄罗斯方块
- Cocos Creator中的Tween
- [iOS]手把手教你实现微信小视频
- Nginx 配置长连接
- 苹果双系统 计算机意外的重新启动,用Boot camp 安装双系统时突然重启,打… - Apple 社区...
- 怎么打开服务器的xls文件,xls是什么文件格式?.xls文件打开方法
- 戴尔电脑风扇声音大的解决方法