Postgresql索引类型

PG索引初探

Posted by 果果 on June 23, 2022

索引是增强数据库性能的利器,在检索某些特定行的时候效率会有很大提升,postgresql中索引类型丰富,每种索引有着不同的应用场景,下面简单介绍一下。

B-TREE索引

B-TREE是我们使用的最多的传统索引,这里就不需要再浪费笔墨来讨论了。

Hash索引

Hash索引是PostgreSQL上的一种特殊的索引,基于hash表,针对键值使用一个HASH函数,因此HASH索引只支持精确查找,不支持范围查找,不支持排序。目前HASH索引也不支持复合索引。在Hash索引中,将键值转换为一个HASH值,然后再进行定位,HASH索引不需要枝节点,因此索引的大小会比普通的B-TREE索引要小。其逻辑结构图如下。 pg0

BRIN索引(对时序数据有效)

BRIN是另外一种体积十分小的索引,这种索引可以用于海量的时序数据,针对物联网应用将会十分有效。BRIN的含义是Block Range Index,顾名思义,是针对块中的值范围进行索引。如下图 如果某个键值是按照规律增长的,比如时序数据,那么使用BRIN将会十分有效。BRIN中存储了某个PAGE中的键值的最小值与最大值。如果键值存在某种单边增长的趋势,那么创建BRIN索引后,根据这个键值做范围扫描的时候,可以根据BRIN索引找到所需要扫描的数据块,跳过其他的所有数据块,快速的将所需的数据扫描出来。BRIN 在索引数据自然倾向于在表的页中分组或排序的情况,并且数据量十分巨大的情况下很有用。 pg1

Partial索引(带where条件的索引)

部分索引(Partial Index)我们可以看作是一种特殊的函数索引,其存储结构也是B-TREE的。 部分索引也称为过滤索引,它只覆盖表数据的一个子集。 它是一个带有 WHERE 子句的索引。 部分索引有助于加快查询速度,同时减少索引的大小,这些索引需要更少的存储空间,它们更易于维护,扫描速度更快。如果您通常使用具有常量值的 WHERE 条件,则部分索引很有用。

在使用数据库的时候,我们也经常会遇到在某张表中,我们经常要根据一个独立值很少的STATUS字段来扫描数据的情况。比如在一张表上,STATUS=1的数据是我们要SELECT出来进行处理的,处理后STATUS就变成了2,因此这张表上的STATUS字段值域是倾斜的,001的记录可能只有几百条,而002的记录有上千万条。 create index idx_partial_status on t_order (status) where status=’1’; 这个索引中只有status=’1’的数据,因此索引十分小。访问的效率也十分高。再复杂一些,我们可以创建类似这样的Partial Index。 create index idx_partial_status on t_order (status) where status in (’1’,’2’); 如果我们的where 条件是status in (’1’,’2’),那么这个索引就能够发挥作用了。

函数索引

PostgreSQL的函数索引与Oracle的函数索引十分类似 一个索引列并不一定是底层表的一个列,也可以是从表的一列或多列计算而来的一个函数或者标量表达式。这种特性对于根据计算结果快速获取表中内容是有用的。 例如,一种进行大小写不敏感比较的常用方法是使用lower函数:

SELECT * FROM test1 WHERE lower(col1) = 'value';

这种查询可以利用一个建立在lower(col1)函数结果之上的索引:

CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));

GIN/GIST索引(全文/空间索引)

GiST 索引不是单独一种索引类型,而是一种架构,可以在这种架构上实现很多不同的索引策略。因此,可以使用 GiST 索引的特定操作符类型根据索引策略的不同而不同(操作符表)。

自定义索引

对于自定义索引,是PostgreSQL的一个更为强大的功能,我们可以通过编写插件的方式来实现自己的索引,根据自己的业务逻辑去对数据创建个性化的索引,从而提升应用访问的效率。这个话题比较复杂,我们下一次找一个专题来讨论。正是因为PG的索引十分复杂,因此十分容易出现索引滥用的情况。比如某个字段上原本就有B-TREE索引,为了某个SQL,我们可能又去创建了其他的索引。如果这样,应用系统经过一段时间的运维后,索引会成为一个大问题。索引导致的行锁问题,写应用变慢问题,会让我们更难去解决。因此在做PostgreSQL数据库索引优化的时候,一定要统筹考虑,密切结合应用的特点去做索引设计与优化。