PostgreSQL技术内幕6:PostgreSQL索引技术

news2024/11/23 23:43:54

文章目录

    • 0. 简介
    • 1.PG索引类型介绍
    • 2. PG创建索引说明及索引属性查看
      • 2.1 创建说明
      • 2.2 查看方式
        • 2.2.1 查看PG默认支持的索引及对应的Handler类型
        • 2.2.2 查看B树索引属性
    • 3. 索引选择
      • 3.1 查看索引情况
    • 4.PG中B-Tree索引原理
      • 4.1 页存储结构
    • 5.索引代码分析
      • 5.1 不同索引结构解析
        • 5.1.1 索引的Handler结构
      • 5.2 BTree关键流程解析
      • 5.2.1 构造函数btbuild

0. 简介

本文主要介绍PG的索引技术,包含PG支持的索引类型,语法,查看方式,以及其中B-Tree索引的原理解析和源码解读。

1.PG索引类型介绍

PG支持多种索引类型:B-tree、Hash、GiST、SP-GiST 、GIN 和 BRIN。不同的索引类型使用不同的算法来适应不同类型的查询,下面是其具体适用情况:
1)B-tree索引:是一种自平衡树,支持O(logn)的插入,删除,访问。
2)Hash索引:通过hash运算查找,只支持等于查找,不支持范围。
3)Gist索引:Gist是通用搜索树(generalized search tree)的缩写,和之前介绍的btree类似(一种平衡树)。但是它和btree不同的是,btree索引常常用来进行例如大于、小于、等于这些操作中,而在实际生活中很多数据其实不适用这种场景,例如地理数据、图像等等。因为Gist索引允许定义规则来将任意类型的数据分布到一个平衡的树中,并且允许定义一个方法使用此表示形式来让某些运算符访问。例如,对于空间数据,GiST索引可以使用 R树,以支持相对位置运算符(位于左侧,右侧,包含等),而对于树形图,R树可以支持相交或包含运算符。
4)SP-GiST索引:SP-GiST 代表空间分区 GiST,主要用于 GIS、多媒体、电话路由以及 IP 路由等数据的索引。
5)GIN索引: 倒排索引,主要用于搜索特定值是不是存在。
6)BRIN索引:BRIN 代表块区间索引(block range indexes),存储了连续物理范围区间内的数据摘要信息。BRIN 也相比 B-树索引要小很多,维护也更容易。对于不进行水平分区就无法使用 B-树索引的超大型表,可以考虑 BRIN。

2. PG创建索引说明及索引属性查看

2.1 创建说明


CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]
    ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
    [ INCLUDE ( column_name [, ...] ) ]
    [ WITH ( storage_parameter [= value] [, ... ] ) ]
    [ TABLESPACE tablespace_name ]
[ WHERE predicate ]

主要参数说明:
UNIQUE:唯一索引,创建索引的列数据不能重复。
CONNCURRENTLY:构建索引时不会阻塞该表正在进行的插入,更新,删除。
METHOD:要使用的索引方法,如btree,hash等。
ASC:升序。
DESC:降序。

2.2 查看方式

2.2.1 查看PG默认支持的索引及对应的Handler类型
select * , obj_description(oid,'pg_am') from pg_am order by 1;

在这里插入图片描述

2.2.2 查看B树索引属性

select a.amname, p.name, pg_indexam_has_property(a.oid, p.name) from pg_am a, unnest(array['can_order','can_unique','can_multi_col','can_exclude']) p(name) where a.amname='btree' order by a.amname;

在这里插入图片描述

3. 索引选择

索引选择可以分两步进行考虑:1.是否建立索引:主要考虑索引的资源占用,对插入和更新的影响以及备份恢复的影响;2.索引类型选择:考虑创建索引以及使用查询的速度,索引大小,索引支持的类型等。

3.1 查看索引情况

1)查看索引

\di

在这里插入图片描述
2)查看所有和磁盘占用

select relname, pg_size_pretty(pg_relation_size(oid)) finsertrom pg_class where relname like 't\_%' or relname='t1' order by relname;

在这里插入图片描述
3)查看索引支持的类型


select opfname from pg_opfamily, pg_am where opfmethod = pg_am.oid and amname='btree' order by 1;

在这里插入图片描述
4)查看所有支持的操作符


select amop.amopopr::regoperator as opfamily_operator, amop.amopstrategy from pg_am am, pg_opfamily opf, pg_amop amop where opf.opfmethod = am.oid and amop.amopfamily =opf.oid and am.amname='btree' and opf.opfname='bool_ops' order by amopstrategy;

在这里插入图片描述

4.PG中B-Tree索引原理

PG中的BTree来源于论文《Efficient locking for concurrent operations on B-trees》,论文中是一种B+树的变形,增加了非叶子节点的右侧的连接,同时引入了引入了“High Key”(下述HK)用于描述当前节点子节点的最大值,PG在此基础上,增加了左侧兄弟节点的连接,对于并发更加友好(并发控制在后续并发控制章节介绍),其结构和特点如图:
在这里插入图片描述
1)树是平衡的
2)支持范围和等值查询以及排序操作
3)是多分支的,深度不会太深,大表4-5层就足够
4)双向互联,可以内部遍历,不需要回到根节点

4.1 页存储结构

PG的索引存储结构和其他页面存储结构一致:

在这里插入图片描述
linp用于索引itup,其存储了每个itup在页面中的实际位置。根据PostgreSQL中对BTree索引结构的描述,分为当前节点是否是最右节点两种类型。由于非最右节点需要一个字段来保存HK,故当对一个页面进行填充时,存在着以下两种方式:
(1)当前节点为非最右节点
在这里插入图片描述
1.将首先将itup3(最大的索引元组)复制到当前节点的右兄弟节点,然后将linp0指向itup3(HK)。
2.去掉linp3。使用linp0来指向页面中的HK。

(2)当前节点为最右节点
在这里插入图片描述
最右节点不需要HK,所以每个linp减一,linp3不需要使用

整体结构
在这里插入图片描述
(1)对于非叶子节点,itup指向下一个节点,而对于叶子节点,itup指向实际物理存储的位置。

(2)Special space中,实现了两个指针,分配用于指向左右兄弟节点。

(3)根据BTree的特性,索引元组为有序,第一个叶子节点中itup3实际为最大索引元组,即HK,第二个叶子节点中itup1实际为最小索引元组,两者相同,故指向了同一物理存储位置。

5.索引代码分析

5.1 不同索引结构解析

5.1.1 索引的Handler结构

每种索引会初始化不同的handler,定义其属性和行为,如创建时的操作,插入时的操作,新加一种索引可以定义不同的hanlder,这也体现了PG的良好的可扩展性。


typedef struct IndexAmRoutine
{
  NodeTag    type;

  /*
   * Total number of strategies (operators) by which we can traverse/search
   * this AM.  Zero if AM does not have a fixed set of strategy assignments.
   */
  uint16    amstrategies;
  /* total number of support functions that this AM uses */
  uint16    amsupport;
  /* opclass options support function number or 0 */
  uint16    amoptsprocnum;
  /* does AM support ORDER BY indexed column's value? */
  bool    amcanorder;
  /* does AM support ORDER BY result of an operator on indexed column? */
  bool    amcanorderbyop;
  /* does AM support backward scanning? */
  bool    amcanbackward;
  /* does AM support UNIQUE indexes? */
  bool    amcanunique;
  /* does AM support multi-column indexes? */
  bool    amcanmulticol;
  /* does AM require scans to have a constraint on the first index column? */
  bool    amoptionalkey;
  /* does AM handle ScalarArrayOpExpr quals? */
  bool    amsearcharray;
  /* does AM handle IS NULL/IS NOT NULL quals? */
  bool    amsearchnulls;
  /* can index storage data type differ from column data type? */
  bool    amstorage;
  /* can an index of this type be clustered on? */
  bool    amclusterable;
  /* does AM handle predicate locks? */
  bool    ampredlocks;
  /* does AM support parallel scan? */
  bool    amcanparallel;
  /* does AM support parallel build? */
  bool    amcanbuildparallel;
  /* does AM support columns included with clause INCLUDE? */
  bool    amcaninclude;
  /* does AM use maintenance_work_mem? */
  bool    amusemaintenanceworkmem;
  /* does AM store tuple information only at block granularity? */
  bool    amsummarizing;
  /* OR of parallel vacuum flags.  See vacuum.h for flags. */
  uint8    amparallelvacuumoptions;
  /* type of data stored in index, or InvalidOid if variable */
  Oid      amkeytype;

  /*
   * If you add new properties to either the above or the below lists, then
   * they should also (usually) be exposed via the property API (see
   * IndexAMProperty at the top of the file, and utils/adt/amutils.c).
   */

  /* interface functions */
  ambuild_function ambuild;
  ambuildempty_function ambuildempty;
  aminsert_function aminsert;
  aminsertcleanup_function aminsertcleanup;
  ambulkdelete_function ambulkdelete;
  amvacuumcleanup_function amvacuumcleanup;
  amcanreturn_function amcanreturn;  /* can be NULL */
  amcostestimate_function amcostestimate;
  amoptions_function amoptions;
  amproperty_function amproperty; /* can be NULL */
  ambuildphasename_function ambuildphasename; /* can be NULL */
  amvalidate_function amvalidate;
  amadjustmembers_function amadjustmembers;  /* can be NULL */
  ambeginscan_function ambeginscan;
  amrescan_function amrescan;
  amgettuple_function amgettuple; /* can be NULL */
  amgetbitmap_function amgetbitmap;  /* can be NULL */
  amendscan_function amendscan;
  ammarkpos_function ammarkpos;  /* can be NULL */
  amrestrpos_function amrestrpos; /* can be NULL */

  /* interface functions to support parallel index scans */
  amestimateparallelscan_function amestimateparallelscan; /* can be NULL */
  aminitparallelscan_function aminitparallelscan; /* can be NULL */
  amparallelrescan_function amparallelrescan; /* can be NULL */
} IndexAmRoutine;

下面简单看btree的handler初始化


Datum
bthandler(PG_FUNCTION_ARGS)
{
  IndexAmRoutine *amroutine = makeNode(IndexAmRoutine);

  amroutine->amstrategies = BTMaxStrategyNumber;
  amroutine->amsupport = BTNProcs;
  amroutine->amoptsprocnum = BTOPTIONS_PROC;
  amroutine->amcanorder = true;
  amroutine->amcanorderbyop = false;
  amroutine->amcanbackward = true;
  amroutine->amcanunique = true;
  amroutine->amcanmulticol = true;
  amroutine->amoptionalkey = true;
  amroutine->amsearcharray = true;
  amroutine->amsearchnulls = true;
  amroutine->amstorage = false;
  amroutine->amclusterable = true;
  amroutine->ampredlocks = true;
  amroutine->amcanparallel = true;
  amroutine->amcanbuildparallel = true;
  amroutine->amcaninclude = true;
  amroutine->amusemaintenanceworkmem = false;
  amroutine->amsummarizing = false;
  amroutine->amparallelvacuumoptions =
    VACUUM_OPTION_PARALLEL_BULKDEL | VACUUM_OPTION_PARALLEL_COND_CLEANUP;
  amroutine->amkeytype = InvalidOid;

  amroutine->ambuild = btbuild;
  amroutine->ambuildempty = btbuildempty;
  amroutine->aminsert = btinsert;
  amroutine->aminsertcleanup = NULL;
  amroutine->ambulkdelete = btbulkdelete;
  amroutine->amvacuumcleanup = btvacuumcleanup;
  amroutine->amcanreturn = btcanreturn;
  amroutine->amcostestimate = btcostestimate;
  amroutine->amoptions = btoptions;
  amroutine->amproperty = btproperty;
  amroutine->ambuildphasename = btbuildphasename;
  amroutine->amvalidate = btvalidate;
  amroutine->amadjustmembers = btadjustmembers;
  amroutine->ambeginscan = btbeginscan;
  amroutine->amrescan = btrescan;
  amroutine->amgettuple = btgettuple;
  amroutine->amgetbitmap = btgetbitmap;
  amroutine->amendscan = btendscan;
  amroutine->ammarkpos = btmarkpos;
  amroutine->amrestrpos = btrestrpos;
  amroutine->amestimateparallelscan = btestimateparallelscan;
  amroutine->aminitparallelscan = btinitparallelscan;
  amroutine->amparallelrescan = btparallelrescan;

  PG_RETURN_POINTER(amroutine);
}

对于不同索引对应的函数和属性在系统初始化时,创建到pg_am、pg_opfamily等系统表中


# Index access method handlers
{ oid => '330', descr => 'btree index access method handler',
  proname => 'bthandler', provolatile => 'v', prorettype => 'index_am_handler',
  proargtypes => 'internal', prosrc => 'bthandler' },
{ oid => '331', descr => 'hash index access method handler',
  proname => 'hashhandler', provolatile => 'v',
  prorettype => 'index_am_handler', proargtypes => 'internal',
  prosrc => 'hashhandler' },
{ oid => '332', descr => 'gist index access method handler',
  proname => 'gisthandler', provolatile => 'v',
  prorettype => 'index_am_handler', proargtypes => 'internal',
  prosrc => 'gisthandler' },

5.2 BTree关键流程解析

5.2.1 构造函数btbuild

在这里插入图片描述
5.2.2 插入流程btinsert
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2096704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

郑州建站网页手机版

随着移动互联网的迅猛发展,越来越多的企业和个人开始重视手机网页的建设。在郑州,这一趋势尤为明显,搭建手机网页已经成为提升品牌形象和吸引客户的重要方式。本文将就郑州建站网页手机版的现状、重要性及注意事项进行探讨。 首先&#xff0c…

LabVIEW中升采样和降采样

升采样 (Upsampling) 和 降采样 (Downsampling) 是信号处理中的两种常见操作,用于改变信号的采样率。它们在数字信号处理(DSP)和许多工程应用中非常重要,尤其是在处理不同采样率的数据流时。 升采样 (Upsampling) 升采样是增加信…

SpringBoot 引入使用消息队列RabbitMQ通信 配置连接 无路由模式

介绍 请先对Rabbitmq的用户和权限配置好在进行往下的操作 依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>下面将演示最简单的例子不过路由 生产者 -&g…

IDEA工程连接不上Mysql数据库

在进行项目创建的时候&#xff0c;发现IDEA工程连接不上数据库。即使登陆的用户名和密码全部正确也报错。 在服务里发现Mysql80没有启动 直接利用命令提示符启动&#xff0c;也显示启动失败。 通过 netstat -ano | findstr :3306 查看数据库默认端口3306的占用情况&#…

【CSP:202009-2】风险人群筛查(Java)

题目链接 202009-2 风险人群筛查 题目描述 求解思路 本题的数据量并不大&#xff0c;直接模拟即可。x和y表示每次读取的坐标点。res1表示经过高风险场地的人数&#xff0c;res2表示在高风险场地停留的人数。s用来记录连续在高风险场地停留的点数。r1表示是否经过高风险场地&…

【学习笔记】卫星通信NTN 3GPP标准化进展分析(三)- 3GPP Release17 内容

一、引言&#xff1a; 本文来自3GPP Joern Krause, 3GPP MCC (May 14,2024) Non-Terrestrial Networks (NTN) (3gpp.org) 本文总结了NTN标准化进程以及后续的研究计划&#xff0c;是学习NTN协议的入门。 【学习笔记】卫星通信NTN 3GPP标准化进展分析&#xff08;一&#xff…

CART算法原理及Python实践

一、CART算法原理 CART&#xff08;Classification And Regression Trees&#xff09;算法是一种用于分类和回归任务的决策树学习技术。它采用贪心策略递归地划分数据集&#xff0c;以构建一棵二叉决策树。CART算法的原理可以概括为以下几个关键步骤&#xff1a; 1. 特征选择与…

如何在 CentOS 6 上安装 Nagios

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 Status: 已弃用 本文涵盖的 CentOS 版本已不再受支持。如果您目前正在运行 CentOS 6 服务器&#xff0c;我们强烈建议升级或迁移到受支持…

什么是单片机?为什么要学习单片机?

实现目标 1、熟悉单片机定义、特点、应用场景、发展历史等&#xff1b; 2、理解为什么要学习单片机&#xff1f;怎样学习单片机&#xff1f; 一、单片机是什么&#xff1f; 1、定义 单片机是集成在一块&#xff08;单&#xff09;芯片上的微型计算机。平时我们把 MCU&#x…

E. Sheep Eat Wolves

https://codeforces.com/gym/104869/problem/E 赛时队友想贪心&#xff0c;贪不了一点&#xff0c;我想了数学办法每次都送固定的发现送过去就不满足了 赛后补&#xff0c;暴力做O&#xff08;n4) 至少要几次才能把安全所有羊送到对岸去 考虑最短路,bfs,用数组存下所有状态 …

nerf论文代码理解

近年来&#xff0c;生成式AI(AGI)快速发展&#xff0c;各类生成式模型层出不群&#xff0c;但我更觉得具有物理意义的生成式AI将是未来革命性技术。因此也在抽空看看关于三维重建的知识&#xff0c;这篇文章就是记录我对nerf的理解。 一、论文理解 首先&#xff0c;需要知道ne…

车载冰箱的介绍

车载冰箱产业链的上游环节主要涉及制冷模块的研发与制造&#xff0c;这一环节根据所采用的制冷技术不同而展现出各自的特点。压缩机制冷模块和半 导体制冷模块是车载冰箱制冷系统的核心组成部分&#xff0c;它们在设计、材料选择和制造工艺上各有千秋。 车载冰箱的原理图 车载…

HTB-Three(云服务)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解Three靶机 渗透过程 信息搜集 服务器开启了22 SSH 和 80 HTTP服务端口 扫描目录 服务器只有一个image图片文件&#xff0c;ssh 需要账号名密码 绑定域名 进行子域名扫描探测 疑似域名&#xff0c;尝…

中秋之美——html5+css+js制作中秋网页

中秋之美——html5cssjs制作中秋网页 一、前言二、功能展示三、系统实现四、其它五、源码下载 一、前言 八月十五&#xff0c;秋已过半&#xff0c;是为中秋。 “但愿人长久&#xff0c;千里共婵娟”&#xff0c;中秋时节&#xff0c;气温已凉未寒&#xff0c;天高气爽&#x…

支付平台构建支付接口供整个公司调用—支付代理商

一、支付平台一般需要对外开放用于满足一体化平台调用 支付平台提供支付接口具有以下必要性&#xff1a; 1. 拓展业务范围&#xff1a;使各类商家和服务提供商能够接入支付服务&#xff0c;从而扩大支付平台的用户群体和业务覆盖范围。 2. 提升用户体验&#xff1a;为不同的应…

音视频-图像篇(YUV和RGB)

文章目录 一、图像基础概念二、YUV与RGB1.YUV分类方式2.YUV“空间-间”的数据划分1&#xff09;UV按照“空间-间”的划分方式&#xff0c;分为YUV444、YUV422、YUV4202&#xff09;YUV“空间-内”的数据划分 3.RGB 三、比较JPG、PNG、GIF、BMP图片格式 一、图像基础概念 像素&…

Python OpenCV 入门指南

引言 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉库&#xff0c;它包含了大量的用于实时图像分析和视频处理的功能。Python 作为一种流行的编程语言&#xff0c;以其易用性和灵活性成为了进行快速原型设计和开发的理想选择。结…

【python2C】排序算法

题&#xff1a;逆序对&#xff08;NXD&#xff09; 对于给定的一段正整数序列a&#xff0c;逆序对就是序列中 a[i]​>a[j]​ 且 i<j 的有序对。 输入格式 第一行&#xff0c;一个正整数 n&#xff0c;表示序列中有 n个数&#xff0c;n<5e5 第二行&#xff0c; n 个正整…

学习之git

github 创建远程仓库 代码推送 Push 代码拉取 Pull 代码克隆 Clone SSH免密登录 Idea集成GitHubGitee码云 码云创建远程仓库 Idea集成Gitee码云 码云连接Github进行代码的复制和迁移GitLab gitlab服务器的搭建和部署 Idea集成GitLabgit概述 一切皆本地 版本控制工具 集中…

读软件开发安全之道:概念、设计与实施15安全测试

1. 安全测试 1.1. 测试是开发可靠、安全代码中的关键一环 1.2. 测试安全漏洞的目的是主动检测 1.3. 模糊测试是一种强大的补充技术&#xff0c;可以帮助我们找到更深层次的问题 1.4. 针对当前漏洞创建的安全回归测试&#xff0c;目的是确保我们不会再犯相同的错误 1.5. 大…