PostgreSQL TID及tuple slot
时间:2022-07-28
本文章向大家介绍PostgreSQL TID及tuple slot,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
1)postgresql默认存储的是堆表,数据按行存储在heap page中。行记录除了存储字段的值外还会存储对应的ctid即行号,表示在哪个页第几个记录。
2)进行select的时候也可以直接指定ctid进行扫描:heap handler中表访问方法的函数为table_tuple_fetch_row_version函数,它来完成通过ctid获取元组。
postgres=# select *from t where ctid='(0,2)';
id1 | id2
-----+-----
2 | b
(1 row)
3)根据ctid扫描的堆栈为
Breakpoint 4, table_tuple_fetch_row_version (rel=0xae9da164, tid=0xbfb2d4c6, snapshot=0x8c06364, slot=0x8c4b7f4) at ../../../src/include/access/tableam.h:1026
1026 return rel->rd_tableam->tuple_fetch_row_version(rel, tid, snapshot, slot);
(gdb) s
heapam_fetch_row_version (relation=0xae9da164, tid=0xbfb2d4c6, snapshot=0x8c06364, slot=0x8c4b7f4) at heapam_handler.c:190
190 BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
(gdb) bt
#0 heapam_fetch_row_version (relation=0xae9da164, tid=0xbfb2d4c6, snapshot=0x8c06364, slot=0x8c4b7f4) at heapam_handler.c:190
#1 0x082f7e08 in table_tuple_fetch_row_version (rel=0xae9da164, tid=0xbfb2d4c6, snapshot=0x8c06364, slot=0x8c4b7f4) at ../../../src/include/access/tableam.h:1026
#2 0x082f86ee in TidNext (node=0x8c4b67c) at nodeTidscan.c:386
#3 0x082cbb1a in ExecScanFetch (node=0x8c4b67c, accessMtd=0x82f85bc <TidNext>, recheckMtd=0x82f8751 <TidRecheck>) at execScan.c:133
#4 0x082cbb70 in ExecScan (node=0x8c4b67c, accessMtd=0x82f85bc <TidNext>, recheckMtd=0x82f8751 <TidRecheck>) at execScan.c:183
#5 0x082f8784 in ExecTidScan (pstate=0x8c4b67c) at nodeTidscan.c:443
#6 0x082c9d5f in ExecProcNodeFirst (node=0x8c4b67c) at execProcnode.c:445
#7 0x082c10ef in ExecProcNode (node=0x8c4b67c) at ../../../src/include/executor/executor.h:239
#8 0x082c319f in ExecutePlan (estate=0x8c4b554, planstate=0x8c4b67c, use_parallel_mode=false, operation=CMD_SELECT, sendTuples=true, numberTuples=0, direction=ForwardScanDirection,
dest=0x8b941dc, execute_once=true) at execMain.c:1646
#9 0x082c1574 in standard_ExecutorRun (queryDesc=0x8bb3e34, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:364
#10 0x082c1411 in ExecutorRun (queryDesc=0x8bb3e34, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:308
#11 0x0846d38b in PortalRunSelect (portal=0x8bde6f4, forward=true, count=0, dest=0x8b941dc) at pquery.c:929
#12 0x0846d0b0 in PortalRun (portal=0x8bde6f4, count=2147483647, isTopLevel=true, run_once=true, dest=0x8b941dc, altdest=0x8b941dc, completionTag=0xbfb2d886 "") at pquery.c:770
#13 0x0846772a in exec_simple_query (query_string=0x8b922e4 "select *from t where ctid='(0,2)';") at postgres.c:1215
#14 0x0846b7e4 in PostgresMain (argc=1, argv=0x8bb7fec, dbname=0x8b8f824 "postgres", username=0x8bb7f14 "pg") at postgres.c:4236
#15 0x083db09d in BackendRun (port=0x8bb49b8) at postmaster.c:4431
#16 0x083da896 in BackendStartup (port=0x8bb49b8) at postmaster.c:4122
#17 0x083d6dff in ServerLoop () at postmaster.c:1704
#18 0x083d674d in PostmasterMain (argc=1, argv=0x8b8d808) at postmaster.c:1377
#19 0x0831d0f4 in main (argc=1, argv=0x8b8d808) at main.c:228
4)而postgres=# set enable_tidscan=off;将这个参数关闭后,就不能通过TID快速进行行扫描了,会走全表扫描,即通过heap handler表方法方法heap_getnextslot函数获取元组。
Breakpoint 1, heap_getnextslot (sscan=0x8c4c21c, direction=ForwardScanDirection, slot=0x8c4b774) at heapam.c:1351
1351 HeapScanDesc scan = (HeapScanDesc) sscan;
(gdb) bt
#0 heap_getnextslot (sscan=0x8c4c21c, direction=ForwardScanDirection, slot=0x8c4b774) at heapam.c:1351
#1 0x082f26c2 in table_scan_getnextslot (sscan=0x8c4c21c, direction=ForwardScanDirection, slot=0x8c4b774) at ../../../src/include/access/tableam.h:875
#2 0x082f2764 in SeqNext (node=0x8c4b67c) at nodeSeqscan.c:80
#3 0x082cbb1a in ExecScanFetch (node=0x8c4b67c, accessMtd=0x82f26e7 <SeqNext>, recheckMtd=0x82f2774 <SeqRecheck>) at execScan.c:133
#4 0x082cbb9c in ExecScan (node=0x8c4b67c, accessMtd=0x82f26e7 <SeqNext>, recheckMtd=0x82f2774 <SeqRecheck>) at execScan.c:200
#5 0x082f27a7 in ExecSeqScan (pstate=0x8c4b67c) at nodeSeqscan.c:112
#6 0x082c9d5f in ExecProcNodeFirst (node=0x8c4b67c) at execProcnode.c:445
#7 0x082c10ef in ExecProcNode (node=0x8c4b67c) at ../../../src/include/executor/executor.h:239
#8 0x082c319f in ExecutePlan (estate=0x8c4b554, planstate=0x8c4b67c, use_parallel_mode=false, operation=CMD_SELECT, sendTuples=true, numberTuples=0, direction=ForwardScanDirection,
dest=0x8b941dc, execute_once=true) at execMain.c:1646
#9 0x082c1574 in standard_ExecutorRun (queryDesc=0x8bb3e34, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:364
#10 0x082c1411 in ExecutorRun (queryDesc=0x8bb3e34, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:308
#11 0x0846d38b in PortalRunSelect (portal=0x8bde6f4, forward=true, count=0, dest=0x8b941dc) at pquery.c:929
#12 0x0846d0b0 in PortalRun (portal=0x8bde6f4, count=2147483647, isTopLevel=true, run_once=true, dest=0x8b941dc, altdest=0x8b941dc, completionTag=0xbfb2d886 "") at pquery.c:770
#13 0x0846772a in exec_simple_query (query_string=0x8b922e4 "select *from t where ctid='(0,2)';") at postgres.c:1215
#14 0x0846b7e4 in PostgresMain (argc=1, argv=0x8bb7fec, dbname=0x8b8f824 "postgres", username=0x8bb7f14 "pg") at postgres.c:4236
#15 0x083db09d in BackendRun (port=0x8bb49b8) at postmaster.c:4431
#16 0x083da896 in BackendStartup (port=0x8bb49b8) at postmaster.c:4122
#17 0x083d6dff in ServerLoop () at postmaster.c:1704
#18 0x083d674d in PostmasterMain (argc=1, argv=0x8b8d808) at postmaster.c:1377
#19 0x0831d0f4 in main (argc=1, argv=0x8b8d808) at main.c:228
4)元组结构参考
https://blog.csdn.net/yanzongshuai/article/details/84195910
5)slot
a)内存中slot结构如上图所示。TupleTableSlot为存储行记录的结构。从数据页读取出记录后,会将其存储到slot中,返回上层。
b)BufferHeapTupleTableSlot结构中第一个成员为HeapTupleTableSlot,而HeapTupleTableSlot第一个成员为TupleTableSlot,为第一个成员方便进行类型强制转换。
c)将TupleTableSlot传到上层后,上层强制转换成HeapTupleTableSlot,进而解析出他的第二个成员tuple,这个tuple的结构为HeapTupleData,包括:t_len:t_data的长度,t_self:TID了,t_tableOid:所属表的OID,t_data:这个为记录头及其数据。
- Facebook Graph API(2)--读取数据之picture
- 使用Dockerfile构建镜像-Docker for Web Developers(5)
- 2018年程序员的出路有哪些
- CSS魔法堂:不得不说的Containing Block
- Facebook Graph API(1)—介绍
- MongoDB学习系列(1)--入门介绍
- 2018年人工智能行业市场预测:市场规模有望突破200亿元大关
- Javascript对象的方法赋值
- CentOS挂载硬盘
- 使用jQuery UI的draggable和droppable完成拖拽功能--介绍
- Angular企业级开发(6)-使用Gulp构建和打包前端项目
- CSS魔法堂:重拾Border之——解构Border
- Angular企业级开发(7)-MVC之控制器
- Angular企业级开发(8)-控制器的作用域
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- AndroidStudio3.6.1打包jar及AndroidStudio4.0打包jar的一系列问题及用法
- 教你如何在js中split函数分割字符串为数组
- [折腾]小型HTTP web服务Caddy及配置PHP
- graftcp一种把指定程序的 TCP 流量重定向到代理的方法
- Flutter应用集成极光推送的实现示例
- android调用C语言实现内存的读取与修改的方法示例
- Android中网络框架简单封装的实例方法
- Auto Remove Torrents:自动删种程序部署
- OpenVZ平台Alpine Linux一键安装脚本
- 使用holder.js生成美观的网页占位图
- Android studio 3.5.2安装图文教程详解
- Android面试必备的JVM虚拟机制详解,看完之后简历上多一个技能!
- 如何在PHP中JSON在线解析
- Linux下如何克隆磁盘/分区命令dd入门
- Android自定义跑马灯文字效果