iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >解析HOT原理
  • 301
分享到

解析HOT原理

解析HOT原理 2017-07-31 09:07:15 301人浏览 绘本
摘要

2020-06-09 19:31:01 一、疑问   前段时间;QQ群里有人对“这个表(0,4)这行数据我做了update操作,查看索引的page数据,看到索引一直指向(0,4),用ctid="(0,4)"查询业务表是查

解析HOT原理

2020-06-09 19:31:01

一、疑问

  前段时间;QQ群里有人对“这个表(0,4)这行数据我做了update操作,查看索引的page数据,看到索引一直指向(0,4),用ctid="(0,4)"查询业务表是查不到数据的;然后我做了表的vacuum,reindex甚至drop/create index,还是这样的”感到疑惑。

  在postgresql8.3实现了(heap only tuple)HOT特性。它存在的目的就是消除表非索引列更新对索引影响。但是它如何工作的呢?

二、解析

  我们来模拟环境

postgres=# create table tbl_hot(id int primary key, info text);
CREATE TABLE
postgres=# insert into tbl_hot select generate_series(1, 4), "lottu";
INSERT 0 4
postgres=# select ctid ,t.* from tbl_hot t;
 ctid  | id | info  
-------+----+-------
 (0,1) |  1 | lottu
 (0,2) |  2 | lottu
 (0,3) |  3 | lottu
 (0,4) |  4 | lottu
(4 rows)
postgres=# d tbl_hot
              Table "public.tbl_hot"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           | not null | 
 info   | text    |           |          | 
Indexes:
    "tbl_hot_pkey" PRIMARY KEY, btree (id)

我们创建表tbl_hot;并插入4条记录。这是我们更新(0,4)这条记录。如下

postgres=# update tbl_hot set info = "rax" where id = 4;
UPDATE 1
postgres=# select ctid ,t.* from tbl_hot t;
 ctid  | id | info  
-------+----+-------
 (0,1) |  1 | lottu
 (0,2) |  2 | lottu
 (0,3) |  3 | lottu
 (0,5) |  4 | rax
(4 rows)

更新之后我们看下索引有变化没?

postgres=# select * from bt_page_items("tbl_hot_pkey", 1);
 itemoffset | ctid  | itemlen | nulls | vars |          data           
------------+-------+---------+-------+------+-------------------------
          1 | (0,1) |      16 | f     | f    | 01 00 00 00 00 00 00 00
          2 | (0,2) |      16 | f     | f    | 02 00 00 00 00 00 00 00
          3 | (0,3) |      16 | f     | f    | 03 00 00 00 00 00 00 00
          4 | (0,4) |      16 | f     | f    | 04 00 00 00 00 00 00 00
(4 rows)
bt_page_items函数是用来:返回关于B-树索引页面上所有项的详细信息,在B树叶子页面中,ctid指向一个堆元组。在内部页面中,ctid的块编号部分指向索引本身中的另一个页面。

  我们可以看出索引没变化。索引存放是表数据的ctid+索引值。使用索引可以快速找到对应记录的ctid。现在 记录id=4 索引的ctid(0,4)跟表对应ctid(0,5)不一致。那是不是索引失效了。我们来测试

postgres=# explain select id from tbl_hot where id = 4;
                                   QUERY PLAN                                    
---------------------------------------------------------------------------------
 Index Only Scan using tbl_hot_pkey on tbl_hot  (cost=0.15..8.17 rows=1 width=4)
   Index Cond: (id = 4)
(2 rows)

  索引没失效;那如何找到对应的记录呢?我们先来看下表存储的page情况

get_raw_page: 根据参数表明、数据文件类型(main、fsm、vm)以及page位置,将当前表文件中的page内容返回。还有一个函数于此同名,只有两个参数,是将第二个参数省略,直接使用"main"。
heap_page_items: 参数是函数get_raw_page的返回值,返回值是将page内的项指针(ItemIddata)以及HeapTupleHeaderData的详细信息。
其中理解下下面字段含义
lp:这是插件自己定义的列,在源码中其实没有,这个是项指针的顺序。
lp_off:tuple在page中的位置
lp_flags: 含义如下
#define LP_UNUSED       0       
#define LP_NORMAL       1       
#define LP_REDIRECT     2       
#define LP_DEAD         3       
t_ctid: 这个是指物理ID
t_infomask2:表字段的个数以及一些flags;其中flag含义
#define HEAP_NATTS_MASK         0x07FF
             
#define HEAP_KEYS_UPDATED       0x2000 
          
#define HEAP_HOT_UPDATED        0x4000  
#define HEAP_ONLY_TUPLE         0x8000  
#define HEAP2_XACT_MASK         0xE000  
postgres=# select * from heap_page_items(get_raw_page("tbl_hot", 0));
 lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid |         t_data         
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------+------------------------
  1 |   8152 |        1 |     34 |    554 |      0 |        0 | (0,1)  |           2 |       2306 |     24 |        |       | x010000000d6c6f747475
  2 |   8112 |        1 |     34 |    554 |      0 |        0 | (0,2)  |           2 |       2306 |     24 |        |       | x020000000d6c6f747475
  3 |   8072 |        1 |     34 |    554 |      0 |        0 | (0,3)  |           2 |       2306 |     24 |        |       | x030000000d6c6f747475
  4 |   8032 |        1 |     34 |    554 |    555 |        0 | (0,5)  |       16386 |       1282 |     24 |        |       | x040000000d6c6f747475
  5 |   8000 |        1 |     32 |    555 |      0 |        0 | (0,5)  |       32770 |      10498 |     24 |        |       | x0400000009726178
(5 rows)

我们来理下:我们通过条件id=4;如何找到对应的记录

  1. 找到指向目标数据tuple的索引tuple(0,4)
  2. 根据获取索引tuple的位置(0,4);找到行指针lp为4的位置。即对应的ctid为(0,5)
  3. 根据ctid为(0,5);我们可以找到两条tuple。根据PG的mvcC机制连判断哪条tuple可见
  4. 可以找到对应tuple

更新多次原理也差不多。

这个时候你会有一个疑问“执行vacuum;清理表tuple(0,4);少了步骤2;那上面的流程就走不通了”。我们来解析下:

postgres=# vacuum tbl_hot;
VACUUM
postgres=# select lp, lp_off, lp_flags, t_ctid, t_infomask2 from heap_page_items(get_raw_page("tbl_hot", 0));
 lp | lp_off | lp_flags | t_ctid | t_infomask2 
----+--------+----------+--------+-------------
  1 |   8152 |        1 | (0,1)  |           2
  2 |   8112 |        1 | (0,2)  |           2
  3 |   8072 |        1 | (0,3)  |           2
  4 |      5 |        2 |        |            
  5 |   8040 |        1 | (0,5)  |       32770
(5 rows)

这时;为了解决这个问题,postgresql会在合适的时候进行行指针的重定向(redirect),这个过程称为修剪。现在按照这种情况我们来理下:我们通过条件id=4;如何找到对应的记录

  1. 找到指向目标数据tuple的索引tuple(0,4)
  2. 根据获取索引tuple的位置(0,4);找到行指针lp为4的位置;这是lp_flags为2表示指针重定向lp为5;即行指针对应的位置是8040
  3. 通过指针可以找到对应tuple。

这是tuple(0,4);既然vacuum;表示可以再使用;但是这是标记是LP_REDIRECT;表明tuple非dead tuple;未进行回收;不可以重复使用。这时你可能会有一个疑问“那什么时候可以回收?”;答案是这个tuple(0,4)不会标记dead tuple。但是执行vacuum;该page是可以回收空间;这个是PG的MVCC处理机制-vacuum的内容;可以分到下个篇幅再讲。这里我们可以简单演示下:

postgres=# update tbl_hot set info = "postgres" where id = 4;
UPDATE 1
postgres=# select lp, lp_off, lp_flags, t_ctid, t_infomask2 from heap_page_items(get_raw_page("tbl_hot", 0));
 lp | lp_off | lp_flags | t_ctid | t_infomask2 
----+--------+----------+--------+-------------
  1 |   8152 |        1 | (0,1)  |           2
  2 |   8112 |        1 | (0,2)  |           2
  3 |   8072 |        1 | (0,3)  |           2
  4 |      5 |        2 |        |            
  5 |   8040 |        1 | (0,6)  |       49154
  6 |   8000 |        1 | (0,6)  |       32770
(6 rows)
postgres=# vacuum tbl_hot;
VACUUM
postgres=# select lp, lp_off, lp_flags, t_ctid, t_infomask2 from heap_page_items(get_raw_page("tbl_hot", 0));
 lp | lp_off | lp_flags | t_ctid | t_infomask2 
----+--------+----------+--------+-------------
  1 |   8152 |        1 | (0,1)  |           2
  2 |   8112 |        1 | (0,2)  |           2
  3 |   8072 |        1 | (0,3)  |           2
  4 |      6 |        2 |        |            
  5 |      0 |        0 |        |            
  6 |   8032 |        1 | (0,6)  |       32770
(6 rows)
postgres=# select ctid,t.* from tbl_hot t;
 ctid  | id |   info   
-------+----+----------
 (0,1) |  1 | lottu
 (0,2) |  2 | lottu
 (0,3) |  3 | lottu
 (0,5) |  5 | lottu
 (0,6) |  4 | postgres
(5 rows)

  最后;当更新的元祖是在其他page;这是索引也会更新;这可以理解是行迁移。这在oracle也是存在这种情况。但是相比oracle更频繁;当然可以设置降低fillfactor;减少这种情况出现。

三、参考

https://blog.csdn.net/xiaohai928ww/article/details/98603707

Https://www.postgresql.org/docs/12/pageinspect.html

您可能感兴趣的文档:

--结束END--

本文标题: 解析HOT原理

本文链接: https://www.lsjlt.com/news/6537.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • CSS的原理解析
    这篇文章主要介绍“CSS的原理解析”,在日常操作中,相信很多人在CSS的原理解析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”CSS的原理解析”的疑惑有所帮助!接下来,请跟着...
    99+
    2024-04-02
  • 解析Redis Cluster原理
    目录一、前言二、为什么需要RedisCluster三、RedisCluster是什么四、节点负载均衡五、什么是一致性哈希六、虚拟节点机制七、RedisCluster采用的什么算法八、...
    99+
    2024-04-02
  • InnoDB insert原理解析
    ...
    99+
    2024-04-02
  • 解析Java8 Stream原理
    目录一、前言二、Stream流水线解决方案2.1、操作如何记录2.2、操作如何叠加2.3、叠加之后的操作如何执行一、前言 首先我们先看一个使用Stream API的示例,具体代码如下...
    99+
    2024-04-02
  • Spring注解@Import原理解析
    目录正文@Import 原理示例 @EnableAsync正文 在项目开发的过程中,我们会遇到很多名字为 @Enablexxx 的注解,比如@EnableApolloConfig、...
    99+
    2023-02-24
    Spring注解@Import Spring @Import Spring注解
  • Vue nextTick的原理解析
    目录Event Loop miscroTask(微任务)UI Render(重点)总结下一个循环nextTick 总结 使用过Vue的小伙伴们都知道,Vue里的nextTick可以获...
    99+
    2024-04-02
  • BeegoAutoRouter工作原理解析
    目录一、前言 二、从一个例子入手✨AutoRouter的解析规则:三、AutoRouter是如何工作的结语一、前言 Beego Web框架应该是国内Go语言社区第一个框架,个人觉得...
    99+
    2024-04-02
  • LRU算法原理解析
    LRU是Least Recently Used的缩写,即最近最少使用,常用于页面置换算法,是为虚拟页式存储管理服务的。 现代操作系统提供了一种对主存的抽象概念虚拟内存,来对主存进行更好地管理。他将主存看成是一个存储在磁盘上的地址空间的高速...
    99+
    2023-01-31
    算法 原理 LRU
  • GoComparableType原理深入解析
    目录介绍内部实现现实中的陷阱与应用errors.Is(*Type)(nil) ≠ nilContext Value Key指针类型Struct 类型介绍 在 Go reflec...
    99+
    2023-01-06
    Go Comparable Type原理 Go Comparable
  • GolangWaitGroup实现原理解析
    原理解析 type WaitGroup struct { noCopy noCopy // 64-bit value: high 32 bits are counter,...
    99+
    2023-02-03
    Go WaitGroup Go WaitGroup实现原理
  • Spring事务原理解析
    目录前言问题描述代码复现排查1. 锁失效2. 事务隔离级别3. 修改Spring事务传播配置解决方案前言 最近在编写公司APP产品的商品砍价功能,其中有一个接口涉及并发访问。自测时通...
    99+
    2022-12-20
    Spring事务管理机制 Spring事务管理方式 Spring事务底层
  • reactSuspense工作原理解析
    目录Suspense 基本应用Suspense 原理基本流程源码解读 - primary 组件源码解读 - 异常捕获源码解读 - 添加 promise 回调源码解读-Suspense...
    99+
    2024-04-02
  • Mybatis 插件原理解析
    Mybati s作为⼀个应⽤⼴泛的优秀的ORM开源框架,这个框架具有强⼤的灵活性,在四⼤组件 (Executor...
    99+
    2024-04-02
  • Golang编译原理解析
    Golang编译原理解析与具体代码示例 在现代编程语言中,编译原理是一个至关重要的领域,它涉及到将高级语言代码转换为机器能够理解和执行的低级指令的过程。作为一门流行的编程语言,Gola...
    99+
    2024-03-06
    原理 编译 golang go语言
  • MySQLxtrabackup物理备份原理解析
    目录一、简介二、xtrabackup备份原理:三、xtrabackup备份流程四、xtrabackup常用命令选项:五、xtrabackup备份实践六、xtrabackup备份日志分...
    99+
    2022-12-21
    MySQL xtrabackup 物理备份原理 MySQL xtrabackup 备份原理
  • C++模板template原理解析
    目录前言1. 函数模板1.1函数模板的概念1.2函数模板的格式1.3 函数模板的原理1.4 函数模板的实例化1.4.1 隐式实例化1.4.2 显式实例化1.5 模...
    99+
    2024-04-02
  • Python matplotlib底层原理解析
    目录1. matplotlib 框架组成2. 脚本层(scripting)3. 美工层(artist)4. 后端层(backend) 复习回顾: 前期,我们已经学习了matplotl...
    99+
    2024-04-02
  • SELECT * 效率低原理解析
    目录效率低的原因索引知识延申联合索引的优势1) 减少开销2)覆盖索引3)效率高4)索引是建的越多越好吗效率低的原因 无论在工作还是面试中,关于SQL中不要用“SELECT *”,都是大家...
    99+
    2023-02-02
    SELECT * 效率低原理 SELECT *
  • SELECT * 效率低原理解析
    目录效率低的原因索引知识延申联合索引的优势1) 减少开销2)覆盖索引3)效率高4)索引是建的越多越好吗效率低的原因 无论在工作还是面试中,关于SQL中不要用“SELEC...
    99+
    2023-02-02
    SELECT * 效率低原理 SELECT *
  • Golang Mutex 原理详细解析
    目录前言Lock单协程加锁加锁被阻塞Unlock无协程阻塞下的解锁解锁并唤醒协程自旋什么是自旋自旋条件自旋的优势自旋的问题Mutex 的模式Normal 模式Starving 模式W...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作