赞
踩
专栏内容:
本文主要分享索引的原理,在postgresql中支持的索引类型的概述。
索引的主要作用是提高数据库查询的效率。当表中有大量记录时,如果没有索引,查询操作可能需要遍历整个表,这会消耗大量的时间,占用大量的CPU和磁盘IO资源。而通过建立索引,数据库系统可以快速地定位到符合查询条件的记录,从而大大提高查询效率。
索引如何可以快速查询呢?
- 索引是一般是将原始无规则的数据,按照特定的数据结构有序排列起业,形成一个新的排序数据结构。数据库中常常采用的数据结构主要以平衡树,如B树或B+树,还有哈希表等。
- 同时索引并不是将一行数据都进行排序,对某一列或多列组合建立索引,这样在有序的数据结构中查找,就可以非常快速的定位到数据的位置,再读取整行数据。这样可以做到索引数据相对于原始表数据,占用非常小的存储空间,甚至可以常驻内存,而原始数据只需要读取所需要的行即可,大大减少磁盘IO使用。
在postgresql 中支持了丰富的索引类型,如btree, gin, gist, spgist, brin等索引类型,每种索引类型适应不同的数据类型进行选择,同时还支持一些用户定义的索引类型,如bloom类型的索引。
下面对索引类型进行概述。
B-Tree索引,是postgresql 中默认的索引类型,因为它可以支持 >
, >=
, =
, <=
, <
等比较操作符,可以应用在很多数据类型,同时可以在多列上创建B-Tree索引。
B-Tree索引的以多路平衡树为存储结构,它有序的存储数据,可以进行高效的搜索,范围查找,以及排序,因此任何可以进行线性排序的数据类型,都可以使用此种索引。
此外B-Tree索引除了查找外,还可以用于order by
,distinct
子句的优化。
Hash索引,存储的数据的HASH KEY,存储结构为hash table,因此在hash 索引中看不到原数据的值,它主要支持等值比较,不支持范围查找,同时也不支持多列上创建Hash索引。
Hash索引支持可以线程排序的数据类型,同时它对数据大小没有限制,因为最终存储的都是HASH KEY。
经常使用HASH索引的场景有:
GIN索引(Generalized Inverted Index)称为通用倒排索引,常被用于复合数据类型,比如数组,jsonb, full text search全文搜索等。
在GIN索引中,对于复合数据中的数据项,存储对应的键值;在GIN索引中存储的每一个元索为 键与发布列表对;而发布列表是包含该键值的行ID,当然同一个行ID可以出现在多个发布列表中,因为一行可以包含多个键值,但是同一键值只保存一次。
对于支持的每种数据类型,都有相应的操作符。
GiST索引(Generalized Search Tree),称为通用搜索树,基于平衡树来实现,它是一种通用的二分查找的索引框架,在此基础上可以实现B树,R树,和其它索引模式。
GiST索引主要用于point,cycle等几何图形,Rang类型,inet类型等等,它的优势在于,开发者可以为用户自定义类型实现一套更符合的索引模式,设计的目标成为数据类型的专家,而不是数据库的专家。
SP-GiST索引(Space-Partitioned Generalized Search Tree)称为空间分区的通用搜索树,它也是一个索引框架。
基于一个支持分区搜索树的数据结构,能够构建一系列不同的非平衡数据结构,如四叉树、k-d树和基数树。
这些结构的共同特点是它们会反复地将搜索空间分割成不需要等大的分区。当搜索与分区规则匹配良好时,搜索速度可以非常快。
BRIN(Block Range Index)是为处理非常大的表而设计的,这些表中的某些列与其在表中的物理位置具有某种自然相关性。
它是基于数据块的索引,而一个数据块中可能会存储多个数据行,索引中会记录数据块的一些摘要信息,这样就可以很快定位到查找键所在的数据块,然后在数据块内再进行查找。
例如,一个存储商店销售订单的表可能有一个日期列,该列记录了每个订单的下单日期,大多数情况下,较早的订单条目也会较早地出现在表中;一个存储邮政编码列的表可能自然地将一个城市的所有代码组合在一起。
由于BRIN索引非常小,扫描索引与顺序扫描相比增加的开销很小,可以避免扫描已知不包含匹配元组的大部分。
块范围的大小在索引创建时由pages_per_range
存储参数确定。索引条目的数量将等于关系的大小(以页面为单位)除以pages_per_range
的选定值。因此,该值越小,索引就越大(因为需要存储更多的块范围摘要信息)。通过选择合适的pages_per_range
值,可以在索引大小和扫描效率之间找到平衡。
Bloom 索引基于 Bloom 过滤器(Bloom filters)提供了一种索引访问方法。
Bloom 过滤器是一种空间效率高的数据结构,用于测试一个元素是否是一个集合的成员。在索引访问方法的上下文中,它允许通过索引创建时确定大小的签名来快速排除不匹配的元组。
签名是索引属性的一种有损表示,因此容易产生误报(false positives);也就是说,它可能会报告一个元素在集合中,而实际上并不在。因此,必须使用堆条目中的实际属性值重新检查索引搜索结果。较大的签名可以降低误报的可能性,从而减少无用的堆访问次数,但当然也会使索引变得更大,从而扫描速度更慢。
这种类型的索引在表具有许多属性且查询测试这些属性的任意组合时最有用。传统的 B-tree 索引比 Bloom 索引更快,但可能需要多个 B-tree 索引来支持所有可能的查询,而 Bloom 索引只需要一个。然而,需要注意的是,Bloom 索引仅支持等值查询,而 B-tree 索引还可以执行不等值和范围搜索。
Postgresql中支持了丰富的索引类型,如常用的Btree,Hash索引,还有针对复合类型的GIN索引,根据类型进行优化的GiST, SP-GiST索引,同时对于非常大的表,基于数据块的BRIN索引,使得索引占用空间更小。
除此之外,还有以扩展形式提供的Bloom索引,用于集合的判断,比传统Btree更有优势。
非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。