认识 PostgreSQL 中与众不同的索引(一)|学习笔记

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: 快速学习认识 PostgreSQL 中与众不同的索引(一)

开发者学堂课程【PostgreSQL 实战进阶认识 PostgreSQL 中与众不同的索引(一)】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/112/detail/1906


认识 PostgreSQL 中与众不同的索引(一)

 

内容介绍:

一、PostgreSQL 中索引的总体介绍

二、BRIN 索引的使用案例

三、数组上建立 GIN 索引

四、快速查找某IP所属地区

五、让 like“%XXX%”中的“XXX”进入索引

六、GIN+JSON 数据类型形成用户画像

索引PostgreSQL 数据库最强大的功能之一。本节课的内容主要包括以下几个部分一部分,PostgreSQL 中索引的总体介绍第二部分,借用一个案例说明BRIN 索引的使用的方法优点;第三部分,介绍在数组上如何使用 GIN 索引;第四部分,通过案例讲解如何快速查找某个 IP 地址的所属地区该部分实际上是对GiST 用途的演示第五部分讲解在 PostgreSQL 中如何让like“%XXX%”中的“XXX”进入索引这个功能是在其他数据库中都无法企及PostgreSQL 可以做到快速索引;最后,使用 GIN+JSON 数据类型实现简单的用户画像场景说明 GIN 和 JSON 数据类型的使用方法

 

一、PostgreSQL 中索引的总体介绍

1、索引的作用

 image.png

(1)最主要的作用在于加快找到某一行数据

数据PostgreSQL 中叫作 TUPLE,即加快 TUPLE 的定位

(2)键,唯一索引约束作用

(3)作为排序

已经存在索引的情况下,不需要重新排序,直接访问索引就可以得到排序的结果。

2、索引的分类

(1)根据索引的算法类型可以分为:

①B-Tree 索引

是最为常用的索引,既能做等值查询,也能做范围查询

②Hash 索引

只能做等值查询可能B-Tree 索引更快

③GiST 索引

其实它不索引类型还是 PostgreSQL 实现的索引框架,只要实现一些函数就可以实现自己用途的一些索引。PostgreSQL 中,最主要的用在 GiST 索引时,在二维和三维的数据的一些特殊的索引中,如包含操作符和图形有没有重叠的操作符

④GIN索引

实际上就是我们常说的倒排索引,常用于全文检索PostgreSQL ,它可以用在数组,或者 JSON 数据类型

⑤BRIN 索引

实际上是物理范围的索引存储在一个表的连续的物理块的范围上的摘要信息如查询一些连续的物理块最大值和最小值当我们查值时,值不在范围内,就可以迅速跳过这些物理块,就可以实现快速过滤大量的物理块通常其他数据库没有 BRIN 索引,是 PostgreSQL 的亮点功能

(2)其他分类方法

PostgreSQL 可以分为唯一索引、部分索引、多列索引、表达式索引(函数索引

3、PostgreSQL 中创建索引的优势

这种优势可以概括为阻塞式创建索引

有些数据库,当创建索引时会把 DML 语句阻塞,但在 PostgreSQL 则不会阻塞 DML 语句,实际上是通过 create index +concurrently 选项实现的。该选项在使用时,PostgreSQL 会执行表两次扫描速度略不会阻塞  DML 语句,也是PostgreSQL 的亮点功能。

PostgreSQL12之前重建索引时不支持 concurrently 参数,在 PostgreSQL12之后,就实现了 concurrently 的支持,当然,在 PostgreSQL12之前可以在同样上使用 concurrently 建不同名的新索引,再把旧索引同样阻塞 DML 语句

 

二、BRIN 索引的使用案例

立一张在表数据,不同的BRIN索引

1、创建表

create table test01(id int,t text);insert into test01(id,t)select seq,rpad(' ',50,'x') from generate_series(1,3000000) as t(seq);

//创建了一张表,同时把表里面的顺序插300万行记录

2、创建索引

默认情况下索引实际上是128个物理块上面建最大值最小值的摘要信息

create index idx_test01_k_brin_128 on test01 using brin(id);

//在默认情况下建立一个 BRIN 索引

create index idx_test01_k_brin_64 on test01 using brin(id) with(pages_per_range=64);

//在64个数据块上建立一个 BRIN 索引

create index idx_test01_k_brin_4 on test01 using brin(id) with(pages_per_range=4);

//在4个数据块上建立一个BRIN索引

create index idx_test01_k btree on test01(id);

//立一个普通的 B-Tree 索引

3、查看创建索引的大小

按照 select pg_relation_size('idx_test01_k_brin_128')的格式输入查询建立的各个索引的大小根据查询结果可以看到,不论何种情况下 BRIN 索引的大小都大大小B-Tree 索引的大小。

 image.png

该查询结果中显示B-Tree 索引大小为67左右,但在4个数据上面建要信息,大小仅有212k两者的大小相差了几十倍。说明 BRIN 索引要比普通索引小很多,所以在插入的数据有一定次序,或者物理块上有一定的数据的范围次序,BRIN 索引会有很大的作用。

仅保留在4个数据块上建立的 BRIN 索引,将些其他的索引先删相继输入 select * from test01 where id=100和 timing,可以发现也可以很快查询出结果

输入 explain analyze select * from test01 where id=100查询执行计划

image.png

可以看出执行时间也很快也进入BRIN 索引由此可见,BRIN 索引的用处是PostgreSQL 数据库很大的亮点。

 

三、数组上建立 GIN 索引

假设先建关于联系人的表,其中应包括以下字段

CREATE TABLE contacts(

id int primary key

name varchar(40),

phone varchar(32)[],

address text);

当今许多人的手机联系电话不仅一个因此我们将其建立为数组。在数组的情况下,建普通索引是行不通但在 PostgreSQL ,对数来说假设要查某电话是谁的手机号则可以通过在数组上建 GIN 索引来完成:

1、创建数据

insert into contacts select seq,seq,array[seq+13600000000, seq+13600000001] from generate_series(1,500000,2) as seq;

大约创建了25万行数据

2、创建 GIN 索引

CREATE INDEX idx_contacts_phone on contacts using gin(phone);

3、查询

SELECT * FROM contacts WHERE phone @ >

array['13600006688 ': 'varchar(32)];

//由于该数据处于数组phone中,因此应使用“ @ >”,其含义是包含即 phone中包含某固定电话后面输入的内容也必须数组,这样就可以查出该联系电话所属的对象

输入命令后很快就可以查出该记录:

image.png

输入explain analyze SELECT * FROM contacts  WHERE phone @ > array['13600006688 ': 'varchar(32)]收集表的统计信息

image.png

可以发现该查询也是通过访问索引完成的执行时间仅为0.1毫秒由此可知,在数组中可以建立 GIN 索引,可以进行搜索。在 PostgreSQL 使用组是一个很好的方案,我们需要快速查找数组时,就在上面建一个 GIN 索引。

 

四、快速查找某 IP 所属地区

除先前创建的表。假设有一张表记录IP 地址范围对应的地区则给定一个公网IP,就可以通过张表的查询其所属的地区通常情况下,张表的格式如下:

create table ipdb1

(

id int,

ip_begin inet,

ip_end inet,

area text,

sp text);

即包括 IP 的 id起始地址结束地址inet PostgreSQL 中IP 地址的范围)、地区和运营商。以下为课堂上给定的相关表 ipdb1:

 image.png

可以看到表中包括了每个起始地址结束地址等信息如 IP 地址为1.0.1.0-1.0.3.225,其属于“福建省”,运营商为“电信”。有了以上地址库,我们就可以进行 IP 地址所属区域的查询

查询方法如下:

1、普通做法

(1)给定一个公网 IP36.22.250.214,查出在那个地区的 SQL 为:

select * from ipdb1 where '36.22.250.214’ > = ip_begin and '36.22.250.214' < = ip_end;

查询结果显示该 IP 地址属于“浙江省”,运营商为“电信”

image.png

查询时间约为308ms,查询时间较长,速度较慢,查询其执行计划:

explain select * from ipdb1 where '36.22.250.214’ > = ip_begin and '36.22.250.214' < = ip_end;

查询结果显示:

image.png

发现该查询过程是全表扫描,而且是 B 型。

(2)改进:加索引

在 IP 起始地址上添加一个索引:

create index idx_ipdb1_ip_begin on ipdb1(ip_begin);

 image.png

查询其执行计划:

explain select * from ipdb1 where '36.22.250.214’ > = ip_begin and '36.22.250.214' < = ip_end;

查询结果显示:

image.png

速度变快。

(3)再加一个索引

在 IP 结束地址上再添加一个索引:

create index idx ipdb1_ip_end on ipdb1(ip_end)

image.png

查询其执行计划:

explain select * from ipdb1 where '36.22.250.214’ > = ip_begin and '36.22.250.214' < = ip_end;

查询结果显示:

image.png

因为该查询过程实际上还是在做索引范围查询,占用资源多,cost 值达到267。而又在结束地址上索引,其实两个索引只能有一个索引起作用。除非把开始的索引删掉但是 cost 值也有268,效率仍旧低下。本质上还是在进行索引的范围扫描。

2、PostgreSQL 中的终极解决方案

创建 RANGE 类型其表明了起始时间和结束时间然后IP 地址的开始和结束地址都放在字段里面在字段里建立 GiST 索引,再查询包含这个  IP 地址的范围,效率会大大提高,相当于是等值查询:

(1)创建表

CREATE TYPE inetrange AS RANGE(

subtype = inet

):  

CREATE TABLE ipdb2(

id integer NOT NULL

ip_range inetrange,

area text,

sp text

)

以下为创建完成的相关表:

image.png

可以看到其中 ip_range 字段包含了起始和结束的 IP 地址,把起始,结束都放在里面。

(2)创GiST 类型的索引

CREATE INDEX idx_ipdb2_ip_range ON ipdb2 USING gist (ip_range);

3查询

select* from ipdb2 where ip_range @>36.22.250.214=inet;

 image.png

查询其执行计划:

explain select * from ipdb2 where ip_range @>36.22.250.214=inet;

查询结果显示:

 image.png

仅需要0.5-0.6mscost 值也降到8.3相对于之前而言,相当假设有大量的系统要来查询 IP 地址可以大大加速程序,同时降cpu 消耗

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
3月前
|
监控 关系型数据库 数据库
PostgreSQL的索引优化策略?
【8月更文挑战第26天】PostgreSQL的索引优化策略?
94 1
|
3月前
|
SQL 关系型数据库 MySQL
SQL Server、MySQL、PostgreSQL:主流数据库SQL语法异同比较——深入探讨数据类型、分页查询、表创建与数据插入、函数和索引等关键语法差异,为跨数据库开发提供实用指导
【8月更文挑战第31天】SQL Server、MySQL和PostgreSQL是当今最流行的关系型数据库管理系统,均使用SQL作为查询语言,但在语法和功能实现上存在差异。本文将比较它们在数据类型、分页查询、创建和插入数据以及函数和索引等方面的异同,帮助开发者更好地理解和使用这些数据库。尽管它们共用SQL语言,但每个系统都有独特的语法规则,了解这些差异有助于提升开发效率和项目成功率。
363 0
|
3月前
|
关系型数据库 数据库 PostgreSQL
PostgreSQL索引维护看完这篇就够了
PostgreSQL索引维护看完这篇就够了
283 0
|
存储 关系型数据库 数据库
PostgreSQL技术大讲堂 - 第28讲:索引内部结构
从零开始学PostgreSQL技术大讲堂 - 第28讲:索引内部结构
729 2
|
关系型数据库 Go 数据库
《提高查询速度:PostgreSQL索引实用指南》
《提高查询速度:PostgreSQL索引实用指南》
586 0
|
关系型数据库 分布式数据库 数据库
PolarDB for PostgreSQL 14:全局索引
PolarDB for PostgreSQL 14 相较于 PostgreSQL 14,提供了更多企业级数据库的特性。本实验将体验其中的全局索引功能。
|
弹性计算 关系型数据库 OLAP
AnalyticDB PostgreSQL版向量索引查询
本案例对比了传统查询和使用向量索引执行查询的执行时间,助您体验使用向量索引查询带来的高效和快捷。
|
存储 SQL 关系型数据库
PostgreSQL插件HypoPG:支持虚拟索引
PostgreSQL插件HypoPG:支持虚拟索引
389 0
|
存储 缓存 关系型数据库
PostgreSQL 14新特性--减少索引膨胀
PostgreSQL 14新特性--减少索引膨胀
475 0
|
6月前
|
SQL 关系型数据库 数据库
RDS PostgreSQL索引推荐原理及最佳实践
前言很多开发人员都知道索引对于数据库的查询性能至关重要,一个好的索引能使数据库的性能提升成千上万倍。但给数据库加索引是一项相对专业的工作,需要对数据库的运行原理有一定了解。同时,加了索引有没有性能提升、性能提升了多少,这些都是加索引前就想知道的。这项繁杂的工作有没有更好的方案呢?有!就是今天重磅推出...
116 1
RDS PostgreSQL索引推荐原理及最佳实践