热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

postgresl系列之NoSQL特性

本文是《PostgreSQL实战》的读书笔记,感兴趣的可以参看本书对应章节。一、PostgreSQL的NoSQL特性PostgreSQL不只是一个关系型数据库&#

本文是《PostgreSQL实战》的读书笔记,感兴趣的可以参看本书对应章节。


一、PostgreSQL的NoSQL特性

PostgreSQL不只是一个关系型数据库,同时支持非关系特性,而且逐步增加对非关系特性的支持。


1.1 为jsonb类型创建索引

jsonb数据类型支持GIN索引。

{"id":1,"user_id":122,"user_name":"1_joker","create_time":"2018-11-25 20:48:10"
}

tbl_user_jsonb中的user_info字段类型是jsonb 。在user_info创建GIN索引。

create index idx_gin ON tbl_user_jsonb USING gin(user_info);

jsonb上的GIN支持 @>??&?| 操作符。例如

-- 使用索引查询
select * from tbl_user_jsonb where user_info @> '{"user_name":"1_joker"}'-- 但是以下基于jsonb键值的查询不会走索引idx_gin:
select * from tbl_user_jsonb where user_info ->>'user_name' = '1_joker';-- 如果要提升基于json类型的键值检索效率,可以在jsonb类型对应的键值上创建索引:
create index idx_gin_user_infob_user_name ON tbl_user_jsonb Using btree(user_info->>'user_name')



1.2 json、jsonb读写性能测试

json写入时比jsonb快,但检索时比jsonb慢。原因:json存储格式为文本而jsonb为二进制,存储格式的不同使的两种json数据类型的处理效率不一样。json类型存储的内容和输入数据一样,当检索json数据时必须重新解析;而jsonb以二进制存储已解析好的数据,当检索jsonb数据时不需要重新解析

通过简答的例子测试json、jsonb的读写性能差异。

--1.创建user_ini表并插入200w数据。
create table user_ini(id int4,user_id int8,user_name character varying(64),create_time timestamp(6) with time zone default clock_timestamp()
);
--1.1插入数据
INSERT INTO user_ini(id,user_id,user_name)
SELECT r,round(random()*2000000),r||'_frances'
FROM generate_series(1,2000000) AS r;--2.使用user_ini表生成json、jsonb数据,创建user_ini_json,user_ini_jsonb表。
CREATE TABLE tbl_user_json(id serial,user_info json);CREATE TABLE tbl_user_jsonb(id serial,user_info jsonb);

json、 jsonb 表写性能测试

根据user_ini数据通过 row_to_json函数向表user_ini_json插入200万json数据。

INSERT INTO tbl_user_json(user_info) SELECT row_to_json(user_ini) FROM user_ini;

在这里插入图片描述

INSERT INTO tbl_user_jsonb(user_info) SELECT row_to_json(user_ini) FROM user_ini;

在这里插入图片描述
可以明显看出来,json的写性能要比jsonb好 。从占用空间来看,同样数量jsonb数据类型占用空间比json稍大。




json、jsonb表读性能测试

根据user_info字段的user_name键的值查询


注意:关闭并行查询 SET max_parallel_workers_per_gather = 0


EXPLAIN ANALYSE SELECT * FROM tbl_user_jsonb WHERE user_info ->>'user_name' = '1_frances';-- 执行计划
Seq Scan on tbl_user_jsonb (cost=0.00..73500.32 rows=10000 width=144) (actual time=0.800..591.076 rows=1 loops=1)Filter: ((user_info ->> 'user_name'::text) = '1_frances'::text)Rows Removed by Filter: 1999999
Planning time: 0.056 ms
Execution time: 591.101 ms

基于user_info字段的user_name 键值创建btree索引

CREATE INDEX idx_jsonb ON tbl_user_jsonb USING btree((user_info->>'user_name'));

再次执行上述查询:

EXPLAIN ANALYSE SELECT * FROM tbl_user_jsonb WHERE user_info ->>'user_name' = '1_frances';-- 执行计划
Bitmap Heap Scan on tbl_user_jsonb (cost=233.93..24043.95 rows=10000 width=144) (actual time=0.372..0.373 rows=1 loops=1)Recheck Cond: ((user_info ->> 'user_name'::text) = '1_frances'::text)Heap Blocks: exact=1-> Bitmap Index Scan on idx_jsonb (cost=0.00..231.43 rows=10000 width=0) (actual time=0.328..0.328 rows=1 loops=1)Index Cond: ((user_info ->> 'user_name'::text) = '1_frances'::text)
Planning time: 0.629 ms
Execution time: 0.429 ms

通过比较执行计划可以看出走了索引,并且SQL时间下降。



为了更好地对比 tbl_user_json、tbl_user_jsonb 表基于键值查询的效率,对user_info字段id键进行范围扫描以对比性能。

CREATE INDEX idx_gin_user_info_id ON tbl_user_json USING btree(((user_info ->>'id')::integer));CREATE INDEX idx_gin_user_infob_id ON tbl_user_jsonb USING btree(((user_info ->>'id')::integer));

--索引创建后,查询tbl_user_json表
EXPLAIN ANALYSE SELECT id,user_info->'id',user_info->'user_name' FROM tbl_user_json
WHERE(user_info->>&#39;id&#39;)::int4 > 1 AND (user_info->>&#39;id&#39;)::int4 < 10000;-- 执行计划
Bitmap Heap Scan on tbl_user_json (cost&#61;214.93..22741.47 rows&#61;10000 width&#61;68) (actual time&#61;1.830..41.511 rows&#61;9998 loops&#61;1)Recheck Cond: ((((user_info ->> &#39;id&#39;::text))::integer > 1) AND (((user_info ->> &#39;id&#39;::text))::integer < 10000))Heap Blocks: exact&#61;173-> Bitmap Index Scan on idx_gin_user_info_id (cost&#61;0.00..212.43 rows&#61;10000 width&#61;0) (actual time&#61;1.762..1.762 rows&#61;9998 loops&#61;1)Index Cond: ((((user_info ->> &#39;id&#39;::text))::integer > 1) AND (((user_info ->> &#39;id&#39;::text))::integer < 10000))
Planning time: 0.389 ms
Execution time: 42.467 ms

查询表tbl_user_json的user_info字段id键值在1到10000范围内走了索引。

EXPLAIN ANALYSE SELECT id,user_info->&#39;id&#39;,user_info->&#39;user_name&#39; FROM tbl_user_jsonb
WHERE(user_info->>&#39;id&#39;)::int4 > 1 AND (user_info->>&#39;id&#39;)::int4 < 10000;-- 执行计划
Bitmap Heap Scan on tbl_user_jsonb (cost&#61;214.93..24224.95 rows&#61;10000 width&#61;68) (actual time&#61;1.269..12.417 rows&#61;9998 loops&#61;1)Recheck Cond: ((((user_info ->> &#39;id&#39;::text))::integer > 1) AND (((user_info ->> &#39;id&#39;::text))::integer < 10000))Heap Blocks: exact&#61;213-> Bitmap Index Scan on idx_gin_user_infob_id (cost&#61;0.00..212.43 rows&#61;10000 width&#61;0) (actual time&#61;1.175..1.175 rows&#61;9998 loops&#61;1)Index Cond: ((((user_info ->> &#39;id&#39;::text))::integer > 1) AND (((user_info ->> &#39;id&#39;::text))::integer < 10000))
Planning time: 0.271 ms
Execution time: 13.074 ms

执行时间明显变短了。

从上面的测试看出&#xff0c;json写入比jsonb快&#xff0c;但检索时比jsonb慢。




二、全文索引对json和jsonb数据类型的支持

对于多数应用来说全文检索很少在数据库中实现&#xff0c;一般使用单独的全文检索引擎&#xff0c;例如基于SQL的全文检索引擎Sphinx。PostgreSQL支持全文检索&#xff0c;对于规模不大的应用如果不想搭建专门的搜索引擎&#xff0c;PostgreSQL的全文检索也可满足需求。



大部分检索需要通过数据库like操作匹配&#xff0c;这种检索方式的主要缺点&#xff1a;


  • 不能很好地支持索引&#xff0c;通常需要全表扫描检索数据&#xff0c;数据量大时检索性能很低。
  • 不能提供检索结果排序&#xff0c;当输出结果数据量非常大时表现更加明显

PostgreSQL全文检索有效地解决这个问题。PostgreSQL全文检索通过以下两种数据类型来实现。




tsvector

tsvector 全文检索数据类型代表一个被优化的可以基于搜索的文档&#xff0c;要将一串字符串转换成tsvector全文检索数据类型。

-- tsvectorSELECT &#39;Hello,cat,how are u? cat is smiling!&#39;::tsvector;-- &#39;Hello,cat,how&#39; &#39;are&#39; &#39;cat&#39; &#39;is&#39; &#39;smiling!&#39; &#39;u?&#39;
--可以看到&#xff0c;字符串的内容被分隔成好几段&#xff0c;但通过::tsvector只是做类型转换&#xff0c;没有进行数据标准处理
--对于英文全文检索可以通过函数 to_tsvecotr进行标准化&#xff1a;SELECT to_tsvector(&#39;english&#39; ,&#39;Hello cat,&#39;)
-- &#39;cat&#39;:2 &#39;hello&#39;:1

tsquery

tsquery 表示一个文本查询&#xff0c;存储用于搜索的词&#xff0c;并且支持布尔操作 &|!

--将字符串转换成 tsquery
SELECT &#39;hello&cat&#39;::tsquery;
-- &#39;hello&#39; & &#39;cat&#39;--上述只是转换成tsquery类型&#xff0c;而并没有做标准化&#xff0c;使用to_tsquery函数可以执行标准化SELECT to_tsquery(&#39;hello&cat&#39;);
-- &#39;hello&#39; & &#39;cat&#39;

--用于检索字符串是否包括"hello" 和 "cat"字符。
SELECT to_tsvector(&#39;english&#39;,&#39;Hello cat, how are u&#39;) &#64;&#64; to_tsquery(&#39;hello&cat&#39;);
-- 结果&#xff1a;t--2. 检索字符串是否包含字符"hello" 和 "dog"
SELECT to_tsvector(&#39;english&#39;,&#39;Hello cat, how are u&#39;) &#64;&#64; to_tsquery(&#39;hello&dog&#39;);
--结果&#xff1a;f



英文全文检索例子

在PostgreSQL10之前全文检索不支持json和jsonb数据类型。10版本则开始支持这两种类型。


推荐阅读
  • Bootstrap Paginator 分页插件详解与应用
    本文深入探讨了Bootstrap Paginator这款流行的JavaScript分页插件,提供了详细的使用指南和示例代码,旨在帮助开发者更好地理解和利用该工具进行高效的数据展示。 ... [详细]
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • 本文探讨了如何通过优化 DOM 操作来提升 JavaScript 的性能,包括使用 `createElement` 函数、动画元素、理解重绘事件及处理鼠标滚动事件等关键主题。 ... [详细]
  • Requests库的基本使用方法
    本文介绍了Python中Requests库的基础用法,包括如何安装、GET和POST请求的实现、如何处理Cookies和Headers,以及如何解析JSON响应。相比urllib库,Requests库提供了更为简洁高效的接口来处理HTTP请求。 ... [详细]
  • CentOS下ProFTPD的安装与配置指南
    本文详细介绍在CentOS操作系统上安装和配置ProFTPD服务的方法,包括基本配置、安全设置及高级功能的启用。 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • 本文将从基础概念入手,详细探讨SpringMVC框架中DispatcherServlet如何通过HandlerMapping进行请求分发,以及其背后的源码实现细节。 ... [详细]
  • 深入理解:AJAX学习指南
    本文详细探讨了AJAX的基本概念、工作原理及其在现代Web开发中的应用,旨在为初学者提供全面的学习资料。 ... [详细]
  • HTML:  将文件拖拽到此区域 ... [详细]
  • 流处理中的计数挑战与解决方案
    本文探讨了在流处理中进行计数的各种技术和挑战,并基于作者在2016年圣何塞举行的Hadoop World大会上的演讲进行了深入分析。文章不仅介绍了传统批处理和Lambda架构的局限性,还详细探讨了流处理架构的优势及其在现代大数据应用中的重要作用。 ... [详细]
  • flea,frame,db,使用,之 ... [详细]
  • C# 中创建和执行存储过程的方法
    本文详细介绍了如何使用 C# 创建和调用 SQL Server 存储过程,包括连接数据库、定义命令类型、设置参数等步骤。 ... [详细]
  • PGXC中的两阶段提交机制及其对事务一致性的保障
    PGXC作为一款基于PostgreSQL的分布式数据库系统,利用Sharding技术将数据分散存储于多个数据库实例中。本文探讨了PGXC的两阶段提交过程及其实现事务强一致性的方法。 ... [详细]
  • 如何在U8系统中连接服务器并获取数据
    本文介绍了如何在U8系统中通过不同的方法连接服务器并获取数据,包括使用MySQL客户端连接实例的方法,如非SSL连接和SSL连接,并提供了详细的步骤和注意事项。 ... [详细]
  • OBS Studio自动化实践:利用脚本批量生成录制场景
    本文探讨了如何利用OBS Studio进行高效录屏,并通过脚本实现场景的自动生成。适合对自动化办公感兴趣的读者。 ... [详细]
author-avatar
PFwX代佳佳ZYYTHFQN
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有