postgrepsql学习

Posted weixin_42412601

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了postgrepsql学习相关的知识,希望对你有一定的参考价值。

目录

1、postgresql----索引失效

https://www.cnblogs.com/alianbog/p/5648455.html

2、postgrep查看sql是否使用索引

EXPLAIN ANALYZE  select * FROM sys_order WHERE is_deleted = 1;

3、模糊查询like优化

一、 模糊查询没有使用索引:
PG中使用索引进行模糊查询
现在数据库中存在一个tb_user(id, name,age)表,并且已经针对name字段创建了索引tb_user_name_idx。

explain analyze select * from tb_user where name like '%aaa%'

发现该SQL语句在name字段上使用的是Seq Scan而不是Index Scan或Bitmap Heap Scan,执行时间在1s以上。

二、模糊查询使用索引:
使用pg_trgm插件
想要在模糊查询时在name字段上使用索引,需要执行如下SQL语句

CREATE EXTENSION pg_trgm;
CREATE INDEX tb_user_name_trgm_gist_idx ON tb_user USING GiST(name GiST_trgm_ops);

此时,再执行:

explain analyze select * from tb_user where name like '%aaa%'

发现该SQL语句在name字段上使用了Bitmap Heap Scan,使用到了新创建的索引,而且执行时间减少到20-30ms。

实际测试:

-- 使用索引: 4ms 5ms
-- 不使用索引:200ms 192ms 218ms
explain analyze select * from sys_order so where order_no like '%9ig_213858%';

4、postgrep自增主键

  • 主键自增长的方式有三种:sequence,serial,identity
https://www.cnblogs.com/wy123/p/13367486.html
  • postgrep,使用identity自增时,主键设置为GENERATED BY DEFAULT AS IDENTITY,插入数据时,如果主键id=null,它会优先使用用户传的id作为主键,这就会报错了,可以再insert的时候,加上OVERRIDING USER VALUE,覆盖用户输入的值(使用系统列定义的自增值)
  • identity详解
https://www.izhangchao.com/internet/internet_228042.html
  • 实际上identify列,也使用了序列,如下:生成的序列默认名为表名_id_seq
  • 获取identify列自增长的下一个值,通过函数nextval
select nextval('test_onduplicatekey_id_seq');

DBeaver中直接点序列,就能看到各个表主键identity生成的默认序列了,注意,是主键使用了identity的方式自增时,才会有。

  • 查询当前表的序列
-- 查询表public.collection的列id的序列
select pg_get_serial_sequence('public.collection','id');
select  nextval('public.collection_id_seq')
-- 查询数据库中有哪些序列
select *  from pg_class where relkind='S';
select *  from pg_class where relkind='S' and relname like '%line_vs_spot%';

5、on CONFLICT语法

insert into sys_user (username,password,email,org_id,is_deleted ,create_time,update_time,create_user_id,create_by) 
		values('lzh123','12345','12345678@qq.com',3,0,'2021-02-19 16:32:08','2021-02-19 16:32:08',1,'admin')
		ON conflict(username,is_deleted) do update set email='66666666@qq.com',password='6666';
https://blog.csdn.net/nmgcfyxl/article/details/105773010
https://vegetable-chicken.blog.csdn.net/article/details/103733927		

6、Postgrep使用json字段,存储json数据

  • postgrep支持同时存储结构化数据和非结构化数据。字段支持json、jsonb的数据类型,一般使用jsonb。
  • 表字段中有json的字段,数据源的url,要加上?stringtype=unspecified
  • 存储json数据时,入参可以使用Object/Map接受json数据,接受到后,再用fastjson转成json数据,与数据库映射的实体类,json字段就使用String去接受json数据就行,然后就当做正常数据插入到数据库中就行了
//使用fastjson将对象转成json数据
String detail=JSON.toJSONString(sysOrder.getDetail());

7、postgrep json字段查询

学习文档:https://www.postgresql.org/docs/current/functions-json.html

-- json数据,可以看成是表里的json字段
-- ::JSON 表示声明前面的字符串或字段为一个JSON字符串对象
-- ->方式获取到的元素依然是json对象
-- ->>方式获取到的元素不是json了,是一个json字符串

-- ->2表示从json数组中,取索引下标为2的元素
select '["a":"foo","b":"bar","c":"baz"]'::json -> 2;
select '["a":"foo","b":"bar","c":"baz"]'::json ->> 2;
-- ->'c'表示取出key是'c'的元素的值
select '["a":"foo","b":"bar","c":"baz"]'::json -> 2->'c';
-- 会报错,因为->> 2获取到的是一个字符串了,已经不是json对象,不能在通过->'c'获取数据
select '["a":"foo","b":"bar","c":"baz"]'::json ->> 2->'c';

-- #> 'a,b,1'表示获取a下的b,b下的索引为1的元素。
-- #>方式获取到的数据,依然是json对象
-- #>>方式获取到的数据,是字符串
select '"a": "b": ["foo","bar"]'::json #> 'a,b,1' 
select '"a": "b": ["foo","bar"]'::json #>> 'a,b,1' 

-- 是否第一个json对象"a":1, "b":2,包含第二个json对象,返回布尔值
select '"a":1, "b":2'::jsonb @> '"b":2'
-- 是否第一个json对象被包含在第二个json对象中
select '"b":2'::jsonb <@ '"a":1, "b":2'

-- json对象中是否包含键为'b'的元素
select '"a":1, "b":2'::jsonb ? 'b'
-- json数组中是否包含元素a
select '["a", "b", "c"]'::jsonb ? 'a'

-- 文本数组array['e', 'a']中是否有元素,存在于json对象或数组中
select '"a":1, "b":2, "c":3'::jsonb ?| array['e', 'a'] 
select '["a", "b", "c"]'::jsonb ?| array['e', 'd'] 

-- 文本数组array['a', 'd']中是否所有元素,存在于json对象或数组中
select '["a", "b", "c"]'::jsonb ?& array['a', 'd'] 
select '"a":1, "b":2, "c":3'::jsonb ?& array['a', 'b'] 

应用:
这种方式,在使用mybatis-plus的apply拼接sql的时候,会把?当成动态参数。
select * from sys_order where detail @? '$.hotelMessage.scheduledDate ? (@ > "2001-12-04 11:10:32" && @ < "2020-12-04 11:10:32" )'
select * from sys_order where detail @? '$.residentsMessage[*].residentName ? (@ starts with "入住")'

这种方式,在使用mybatis-plus的apply拼接sql的时候,会存在sql注入的风险
select * from sys_order where detail @@ '$.residentsMessage[*].residentName starts with "入住"'
select * from sys_order where detail @@ '$.hotelMessage.scheduledDate > "2001-12-04 11:10:32" &&  $.hotelMessage.scheduledDate < "2020-12-04 11:10:32" '
如何避免sql注入的风险?
	.apply(ObjectUtil.isNotEmpty(sysOrderQO.getResidentName()), "detail @@ 0", "$.residentsMessage[*].residentName starts with \\"" + sysOrderQO.getResidentName() + "\\"")
	.apply(ObjectUtil.isNotNull(sysOrderQO.getScheduledDateStart()), "detail @@ 0", "$.hotelMessage.scheduledDate >= \\"" + minimumOfLocalDate(sysOrderQO.getScheduledDateStart()) + "\\"")
	.apply(ObjectUtil.isNotNull(sysOrderQO.getScheduledDateEnd()), "detail @@ 0", "$.hotelMessage.scheduledDate < \\"" + maximumOfLocalDate(sysOrderQO.getScheduledDateEnd()) + "\\""); 
注意:0默认给加单引号

批量查询:
select * from test.devices_device dd where extra_properties
->>'ChannelDeviceId' in ('11010500491310100541','11010500491310109069','1');
SELECT  * FROM alarm_config WHERE  is_deleted=0 AND (condition_content @? '$.deviceConditions[*].deviceIds ? ( @ == 1 || @ == 1529404051424239713)');
SELECT  * FROM alarm_config WHERE  is_deleted=0 AND condition_content @@ '$.deviceConditions[*].deviceIds == 1 || $.deviceConditions[*].deviceIds == 1529404051424239713' ;

数组嵌套查询:
[
    [
        
            "key": "SupplyAirHumidity6",  
            "value": "1",         
            "operator": 0,         
            "deviceId": 1,
            "categoryId": 123
        ,
        
            "key": "SupplyAirHumidity6",
            "value": "1",
            "operator": 0,
            "deviceId": 2,
            "categoryId": 456
        ,
        
            "key": "SupplyAirHumidity66",
            "value": "1",
            "operator": 0,
            "deviceId": 4,
            "categoryId": 789
        
    ],
    [
        
            "key": "SupplyAirHumidity666",
            "value": "1",
            "operator": 0,
            "deviceId": 5,
            "categoryId": 101112
        
    ]
]
SELECT * FROM table where condition_content @@ '$[*][*].categoryId == 123';

以上是关于postgrepsql学习的主要内容,如果未能解决你的问题,请参考以下文章

postgrepsql学习

postgrepsql学习

postgrepsql 创建函数

postgrepsql 常用命令

postgrepsql 查看单表大小

编码表字节流字节缓冲流