1、概述

Gist(Generalized Search Tree),即通用搜索树。和btree一样,也是平衡的搜索树。
和btree不同的是,btree索引常常用来进行例如大于、小于、等于这些操作中,而在实际生活中很多数据其实不适用这种场景,例如地理数据、图像等等。如果我们想要查询在某个地方是否存在某一点,即判断地理位置的"包含"那么我们就可以使用gist索引了。
因为gist索引允许定义规则来将任意类型的数据分布到一个平衡的树中,并且允许定义一个方法使用此表示形式来让某些运算符访问。例如,对于空间数据,GiST索引可以使用 R树,以支持相对位置运算符(位于左侧,右侧,包含等),而对于树形图,R树可以支持相交或包含运算符。

2、结构

Gist索引的结构可以简单概括为:

  • 树结构,深度一致。Tree-structure
  • 索引PAGE内的数据不按KEY的顺序排序。No order within pages
  • 不同的索引PAGE的内容可能存在交叉,例如RANGE类型,值交叉。Key ranges of pages can overlap
  • 由于第三条,所以搜索一条TUPLE时,可能会找到多个满足条件的PAGE。No single “correct” location for
    a particular tuple

2.1、单个gist索引page的结构:

索引page中存放的是key+tid,例如上图中[100,150]表示100到150这个范围,(1,10)表示行的ctid(第几个HEAP PAGE,里面的第几条记录)。同时,这些存放的值在索引中是无序的。

2.2、Gist两级索引结构:
GiST两级索引长这样,上一级代表下一级中单个INDEX PAGE的大范围。

例如我们现在查询[55,60]这个范围,在索引中是如何工作的呢?

3、使用实例

在使用之前,我们先来看看Gist索引的使用场景有哪些。
因为gist是一个通用的索引接口,所以可以使用GiST实现b-tree, r-tree等索引结构。
不同的类型,支持的索引检索也各不一样。例如:
1、几何类型,支持位置搜索(包含、相交、在上下左右等),按距离排序。
2、范围类型,支持位置搜索(包含、相交、在左右等)。
3、IP类型,支持位置搜索(包含、相交、在左右等)。
4、空间类型(PostGIS),支持位置搜索(包含、相交、在上下左右等),按距离排序。
5、标量类型,支持按距离排序。

3.1、几何类型检索
创建一个存放几何数据的表:

bill@bill=>create table t_gist (id int, pos point);
CREATE TABLE
bill@bill=>insert into t_gist select generate_series(1,100000), point(round((random()*1000)::numeric, 2), round((random()*1000)::numeric, 2));
INSERT 0 100000
bill@bill=>select * from t_gist limit 5;id |       pos
----+-----------------1 | (614.87,412.97)2 | (248.71,779.61)3 | (976.17,826.79)4 | (999.39,126.9)5 | (651.61,364.49)
(5 rows)

在pos列上创建gist索引:

bill@bill=>create index idx_t_gist_1 on t_gist using gist (pos);
CREATE INDEX

查询:
可以发现gist索引支持bitmap scan和index scan。

bill@bill=>explain (analyze,verbose,timing,costs,buffers) select * from t_gist where circle '((100,100) 10)'  @> pos;    QUERY PLAN
------------------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on bill.t_gist  (cost=2.35..113.84 rows=100 width=20) (actual time=0.107..0.157 rows=35 loops=1)Output: id, posRecheck Cond: ('<(100,100),10>'::circle @> t_gist.pos)Heap Blocks: exact=32Buffers: shared hit=38->  Bitmap Index Scan on idx_t_gist_1  (cost=0.00..2.33 rows=100 width=0) (actual time=0.093..0.093 rows=35 loops=1)Index Cond: (t_gist.pos <@ '<(100,100),10>'::circle)Buffers: shared hit=6Planning Time: 0.188 msExecution Time: 0.268 ms
(10 rows)bill@bill=>explain (analyze,verbose,timing,costs,buffers) select * from t_gist where circle '((100,100) 1)' @> pos order by pos <-> '(100,100)' limit 10; QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------Limit  (cost=0.28..12.72 rows=10 width=28) (actual time=0.084..0.085 rows=1 loops=1)Output: id, pos, ((pos <-> '(100,100)'::point))Buffers: shared hit=4->  Index Scan using idx_t_gist_1 on bill.t_gist  (cost=0.28..124.73 rows=100 width=28) (actual time=0.082..0.083 rows=1 loops=1)Output: id, pos, (pos <-> '(100,100)'::point)Index Cond: (t_gist.pos <@ '<(100,100),1>'::circle)Order By: (t_gist.pos <-> '(100,100)'::point)Buffers: shared hit=4Planning Time: 0.175 msExecution Time: 0.129 ms
(10 rows)

3.2、标量类型
因为gist可以实现btree的索引结构,所以我们也可以在例如数字这种标量类型上使用gist索引(虽然一般都不如btree索引效果好),不过我们还需要使用btree_gist索引插件。

bill@bill=>create extension btree_gist ;
CREATE EXTENSION
bill@bill=>create table t_btree(id int,info text);
CREATE TABLE
bill@bill=>insert into t_btree select generate_series(1,100000),md5(random()::text);
INSERT 0 100000

创建gist索引:

bill@bill=>create index idx_t_btree on t_btree using gist(id);
CREATE INDEX

查询:

bill@bill=>explain (analyze,verbose,timing,costs,buffers) select * from t_btree order by id <-> 100 limit 1;QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------Limit  (cost=0.28..0.32 rows=1 width=41) (actual time=0.072..0.073 rows=1 loops=1)Output: id, info, ((id <-> 100))Buffers: shared hit=4->  Index Scan using idx_t_btree on bill.t_btree  (cost=0.28..3798.18 rows=100000 width=41) (actual time=0.071..0.071 rows=1 loops=1)Output: id, info, (id <-> 100)Order By: (t_btree.id <-> 100)Buffers: shared hit=4Planning Time: 0.334 msExecution Time: 0.118 ms
(9 rows)

4、总结

Gist索引实现首先要将数据聚集,聚集后,在单个组内包含的KEY+HEAP行号会放到单个INDEX PAGE中。
聚集的范围作为一级结构,存储在GiST的entry 中,便于检索。
既然灵魂是聚集,那么GiST的性能就和他的聚集算法息息相关,PostgreSQL把这个接口留给了用户,用户在自定义数据类型时,如果要自己实现对应的GIST索引,那么就好好考虑这个类型聚集怎么做吧。
PostgreSQL内置的range, geometry等类型的GIST已经帮你做好了,你只需要做新增的类型,比如你新增了一个存储人体结构的类型,存储图片的类型,或者存储X光片的类型,怎么快速检索它们,那就是你要实现的GIST索引聚集部分了。

参考链接:

https://habr.com/ru/company/postgrespro/blog/444742/

https://www.cnblogs.com/cmi-sh-love/p/kong-jian-shud-ju-suo-yinRTree-wan-quan-jie-xi-jiJa.html

https://github.com/digoal/blog/blob/master/201906/20190604_03.md

PostgreSQL索引详解5——Gist索引相关推荐

  1. 【MySQL】MySQL的存储引擎和索引详解(聚集索引和非聚集索引)

    目录 一.MySQL存储引擎 1.1  Innodb引擎 1.2 MyISAM引擎 1.3 InNoDB与MyISAM异同 1.4 两种引擎的选择 二.索引(Index) 2.1 InnoDB存储引擎 ...

  2. MySQL字符串前缀索引详解

    MySQL字符串前缀索引详解 1. 前缀索引与全部索引概念 2. 前缀索引与全部索引数据结构 3. 前缀索引与全部索引引执行流程 4. 前缀索引长度如何取舍 5. 前缀索引对覆盖索引的影响 6. 其他 ...

  3. mysql 联合索引详解

    mysql 联合索引详解 联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分.例如索引是key index (a,b,c). ...

  4. oracle数据库中索值,Oracle数据库中的索引详解

    Oracle数据库中的索引详解以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一 ROWID的概念 存储了row在数据文 ...

  5. mysql索引详解(转)

    什么是索引 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面的 ...

  6. MS SQL Server:分区表、分区索引详解

    MS SQL Server:分区表.分区索引 详解 1. 分区表简介 使用分区表的主要目的,是为了改善大型表以及具有各种访问模式的表的可伸缩性和可管理性.  大型表:数据量巨大的表.  访问模式: ...

  7. 【Python】Numpy数组的切片、索引详解:取数组的特定行列

    [Python]Numpy数组的切片.索引详解:取数组的特定行列 文章目录 [Python]Numpy数组的切片.索引详解:取数组的特定行列 1. 介绍 2. 切片索引 2.1 切片索引先验知识 2. ...

  8. hugegraph图数据库索引详解

    hugegraph图数据库索引详解 版权声明:转载请注明出处 https://blog.csdn.net/u010260089/article/details/86712983 前言 在<技术文 ...

  9. Oracle索引详解(索引的原理,创建索引,删除索引,修改索引等)

    Oracle索引详解 一.索引概述 Oracle作为关系型数据库,用户查找数据与行的物理位置无关,表中的每一行均用一个ROWID来标识,当Oracle数据库中存储海量的记录时,就意味着有大量的ROWI ...

最新文章

  1. python中where函数_如何在python中基于Where函数获取两列值
  2. XMT.com超200万被区块链终端交易
  3. pygame的学习以及python的巩固(窗口尺寸的显示)
  4. Java的List转Scala的数组
  5. Spring Boot Servlet
  6. C++面向对象思想 两条直线交点计算
  7. php域名墙检测,php 网站域名被墙判断请求方法
  8. android中文api (59) —— TabHost.TabSpec
  9. GDAL读取S-57海图数据中文属性值乱码问题解决
  10. iOS获取音频设备信息
  11. 11.22 访问日志不记录静态文件 11.23 访问日志切割 11.24 静态元素过期时间
  12. matlab解隐式差分格式,【毕业设计(论文)】二维热传导方程有限差分法的MATLAB实现...
  13. 计算机3大总线名词解释,计算机名词解释-- 总线.doc
  14. Linux内核API之class_create与class_destroy
  15. CTR --- FNN原理,及tf2实现
  16. 强大的文件管理利器-恒辉通用文件管理工具
  17. python numpy读取数据_python机器学习(七)数据分析利器,NumPy,pandas与Matplotlib
  18. PHP单例模式 构造方法
  19. 24 直面配分函数Confronting Partition Function
  20. 人机博弈之(一)------博弈介绍

热门文章

  1. 第953期机器学习日报(2017-04-28)
  2. mysql8.0以及SQLyong安装以及配置
  3. 5道题,教你参破滑动窗口的解法
  4. .net C# 苹果消息推送 工具类
  5. 随机数分布c语言,C++ piecewise_linear_distribution分段线性分布随机数用法详解
  6. GOF_23中设计模式之简单工厂
  7. spring boot 中出现DataBufferLimitException: Exceeded limit on max bytes to buffer :262144
  8. 【OpenAirInterface知识-3】OAI端到端部署之5G基站部署
  9. 科笛上市一度破发:公司市值67亿港元 红杉与云锋是股东
  10. xss-labs/level-3