Index Scan涉及到两部分的内容Heap Only Tuple和index-only-scan。

什么是Heap Only Tuple(HOT)?

例如:Update a Row Without HOT

testdb=# \d tbl
Table "public.tbl"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
id | integer | | not null |
data | text | | |
Indexes:
"tbl_pkey" PRIMARY KEY, btree (id)

假设更新一条数据

testdb=# UPDATE tbl SET data = 'B' WHERE id = 1000;

如果没有HOT机制,则不仅仅增加一个新的元组Tuple2,而且还增加了一个Index元组,如下图所示

如果Update a Row With HOT,那么更新后会怎样?

根据上图仅仅增加一个新的元组Tuple2。

同时Tuple1被设置了HEAP_HOT_UPDATED, Tuple2被设置了HEAP_ONLY_TUPLE.



更新后数据是怎么通过Index检索到的?



根据图(a)Before Pruning ,通过Index找到Tuple1,再根据Tuple1中的t_ctid找到Tupe2。此时会读取到两个元组Tuple1和Tuple2,根据MVCC机制决定读取Tupel1还是Tuple2.

上述的查找过程会带来问题:如果dead Tuple被删除了如:Tuple1,此时通过index就无法找到Tuple2.

为了解决这个问题,在合适的时候,PostgreSQL会像图(b)After Pruning中所示的现将Header中“1”指向“2”,再将“2”指向Tuple2. 这就被称为“Pruning”。

具体的执行时间可参考

https://github.com/postgres/postgres/blob/master/src/backend/access/heap/README.HOT

SELECT, UPDATE, INSERT and DELETE文被执行的时候,会进行pruning 处理。

![avatar]https://img2018.cnblogs.com/blog/1922961/202001/1922961-20200117160110815-2048897544.png)

在适当的时候,PostgreSQL会删除dead Tuple。PostgreSQL中被称为“Defragmentation”

注意:Defragmentation 的花费比VACUUM的花费要小,因为Defragmentation处理并不删除Index Tuple

下面的两个场景不适用于HOT

(1) 更新的元组和旧的原组不在一个page上,比如下图的图a此时需要增加一个新的Index Tuple指向新的Tuple

(2) 如果Index值被更新了,这时需在Index page中新增一个Index Tuple

HOT相关的统计信息可参考统计表pg_stat_all_tables

什么是Index-Only Scan?

为了降低I/O(Input/Output)的花费,当SELECT的目标列就是index 列时,直接使用Index key不去使用Table page。

例如下表

testdb=# \d tbl
Table "public.tbl"
Column | Type | Modifiers
--------+---------+-----------
id | integer |
name | text |
data | text |
Indexes:
"tbl_idx" btree (id, name)

表中已经插入的两个元组:

‘Tuple_18’, id的值是 ‘18’,name 的值是 ‘Queen’,这个元组存储在第0个 page.

‘Tuple_19’, id的值是‘19’, name 的值是 ‘BOSTON’, 这个元组存储在第1个 page

执行下面的SELECT文

testdb=# SELECT id, name FROM tbl WHERE id BETWEEN 18 and 19;
id | name
----+--------
18 | Queen
19 | Boston
(2 rows)

具体的过程如下:

这个查询要获取id, name这两列的值,并且"tbl_idx"是由这两列组成的。所以使用index scan。

咋看下是不需要获取table page的,因为index tuple已经包含需要的值了。

但是由于PostgreSQL还需要check元组的可见性visibility,index tuple中并不含有可见性visibility的信息(heap Tuple中才有的t_xmin and t_xmax 信息)。所以PostgreSQL不得不去使用table data。

为了解决这个问题,PostgreSQL使用了visibility map记录表的可见性,如下图。

如果所有tuple存储的page是可见的,PostgreSQL就直使用index key不去使用table page。否则的话,就去读table page检查其可见性。

在本例中Tuple_18直接使用index key,Tuple_19则需要使用table page检查其可见性。

参考资料:http://www.interdb.jp/pg/pgsql07.html

PostgreSQL内核学习笔记十一(索引)的更多相关文章

  1. PostgreSQL内核学习笔记四(SQL引擎)

    PostgreSQL实现了SQL Standard2011的大部分内容,SQL处理是数据库中非常复杂的一部分内容. 本文简要介绍了SQL处理的相关内容. 简要介绍 SQL文的处理分为以下几个部分: P ...

  2. EPROCESS 进程/线程优先级 句柄表 GDT LDT 页表 《寒江独钓》内核学习笔记(2)

    在学习笔记(1)中,我们学习了IRP的数据结构的相关知识,接下来我们继续来学习内核中很重要的另一批数据结构: EPROCESS/KPROCESS/PEB.把它们放到一起是因为这三个数据结构及其外延和w ...

  3. python3.4学习笔记(十一) 列表、数组实例

    python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...

  4. Linux内核学习笔记-2.进程管理

    原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  5. Linux内核学习笔记-1.简介和入门

    原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  6. Linux内核学习笔记二——进程

    Linux内核学习笔记二——进程   一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...

  7. 20135316王剑桥Linux内核学习笔记

    王剑桥Linux内核学习笔记 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 计算机是如何工作的 个人理 ...

  8. Go语言学习笔记十一: 切片(slice)

    Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...

  9. KTHREAD 线程调度 SDT TEB SEH shellcode中DLL模块机制动态获取 《寒江独钓》内核学习笔记(5)

    目录 . 相关阅读材料 . <加密与解密3> . [经典文章翻译]A_Crash_Course_on_the_Depths_of_Win32_Structured_Exception_Ha ...

随机推荐

  1. 【学习笔记】Linux基础(二):Linux的基本操作

    二.Linux的基本操作 0.正确的开关机操作 开机和登陆: 安全起见,一般不使用最高权限的root账户登入系统,光立系统时再使用 登录时为login程序提供账户名和密码即可,密码不会被显示,登陆后显 ...

  2. 利用jQuery动态添加input输入框,并且获取他的值

    动态添加 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEnco ...

  3. Spring使用外部属性文件

    一.在 Spring Config 文件中配置 Bean 时,有时候需要在 Bean 的配置里添加 系统部署的细节信息, 如文件路径,数据源配置信息.而这些部署细节实际上需要在配置文件外部来定义. 二 ...

  4. [python]Mongodb

    文档: http://api.mongodb.com/python/current/tutorial.html 安装: 官网直接下载安装, mac上brew安装的下载太慢, 打算手动安装 使用: 开启 ...

  5. c++利用初始化列表在类内部和类外部定义构造函数的区别

    case 1:在类外定义构造函数,所有data member都在初始化列表中进行初始化. class SupportClass { public: SupportClass() { cout < ...

  6. Elasticsearch原理学习--为什么Elasticsearch/Lucene检索可以比MySQL快?

    转载于:http://vlambda.com/wz_wvS2uI5VRn.html 同样都可以对数据构建索引并通过索引查询数据,为什么Lucene或基于Lucene的Elasticsearch会比关系 ...

  7. VMware vCenter Server6.0安装及群集配置介绍

    在本项目中,将在VMware Workstation 模拟的Windows Server 2008 R2虚拟机中安装VMware vCenter Server ,并且使用vCenter Server捆 ...

  8. 手把手教你使用数据可视化BI软件创建仓库可视化管理大屏

    灯果数据可视化BI软件是新一代人工智能数据可视化大屏软件,内置丰富的大屏模板,可视化编辑操作,无需任何经验就可以创建属于你自己的大屏.大家可以在他们的官网下载软件.   本文以仓库可视化管理大屏为例为 ...

  9. VSTO开发指南(VB2013版) 第三章 Excel编程

    通过前两章的内容,有了一定的基础,但进入第三章,实例的步骤非常多,并且随着VS版本的升级,部分功能菜单界面发生了很大变化,所以,第三章的案例我将逐步编写! 实例3.1的目标就是给Excel写一个加载宏 ...

  10. Android布局管理器-使用TableLayout表格布局管理器实现简单的用户登录页面

    场景 Android布局管理器-使用FrameLayout帧布局管理器显示层叠的正方形以及前景照片: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article ...