元组结构和DML操作
一、元组结构¶
元组结构:HeapTupleHeaderData结构、空值位图及用户数据
HeapTupleHeaderData结构: - t_xmin保存插入此元组的事务的txid。 - t_xmax保存删除或更新此元组的事务的txid。如果尚未删除或更新此元组,则t_xmax设置为0,即无效。 - t_cid保存命令标识(command id,cid),cid的意思是在当前事务中,执行当前命令之前执行了多少SQL命令,从零开始计数。例如,假设我们在单个事务中执行了3条INSERT命令BEGIN;INSERT;INSERT;INSERT;COMMIT;。如果第一条命令插入此元组,则该元组的t_cid会被设置为0。如果第二条命令插入此元组,则其t_cid会被设置为1,以此类推。 - t_ctid保存着指向自身或新元组的元组标识符(tid)。tid用于标识表中的元组。在更新该元组时,t_ctid会指向新版本的元组,否则t_ctid会指向自己。
行结构
PostgreSQL自带了一个第三方贡献的扩展模块pageinspect,可用于检查数据库页面的具体内容。
2. DML¶
1. INSERT¶
假设元组是由txid=99的事务插入页面中的,在这种情况下,被插入元组的首部字段会依以下步骤设置。 Tuple_1: - t_xmin设置为99,因为此元组由txid=99的事务所插入。 - t_xmax设置为0,因为此元组尚未被删除或更新。 - t_cid设置为0,因为此元组是由txid=99的事务所执行的第一条命令插入的。 - t_ctid设置为(0,1),指向自身,因为这是该元组的最新版本。
1 2 3 4 5 6 7 8 9 10 11 |
|
2. DELETE¶
在删除操作中,目标元组只是在逻辑上被标记为删除。目标元组的t_xmax字段将被设置为执行DELETE命令事务的txid。 假设Tuple_1被txid=111的事务删除。在这种情况下,Tuple_1的首部字段t_xmax被设为111。 如果txid=111的事务已经提交,就不一定要Tuple_1。通常不需要的元组在PostgreSQL中被称为死元组(dead tuple)。
3. UPDATE¶
在更新操作中,PostgreSQL在逻辑上实际执行的是删除最新的元组,并插入一条新的元组。 假设由txid=99的事务插入的行,被txid=100的事务更新两次。 当执行第一条UPDATE命令时,Tuple_1的t_xmax被设为txid=100,在逻辑上被删除,然后Tuple_2被插入,接下来重写Tuple_1的t_ctid以指向Tuple_2。Tuple_1和Tuple_2的头部字段设置如下。
Tuple_1: - t_xmax被设置为100。 - t_ctid从(0,1)被改写为(0,2)。
Tuple_2: - t_xmin被设置为100。 - t_xmax被设置为0。 - t_cid被设置为0。 - t_ctid被设置为(0,2)。
当执行第二条UPDATE命令时,和第一条UPDATE命令类似,Tuple_2被逻辑删除,Tuple_3被插入。Tuple_2和Tuple_3的首部字段设置如下。
Tuple_2: - t_xmax被设置为100。 - t_ctid从(0,2)被改写为(0,3)。
Tuple_3: - t_xmin被设置为100。 - t_xmax被设置为0。 - t_cid被设置为1。 - t_ctid被设置为(0,3)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
块空间的清理¶
块中被删除的行的是逻辑上删除,物理上还保留在块中,如果长时间不清理,会造成垃圾空间膨胀,设想,如果一个块中有50%垃圾,那么就浪费50%的存储空间如果读到内存,也会浪费50%的内存空间,所以需要定期的清理,而清理的工作由AutoVacuum来操作,或者我们也可以手动操作。
pg_freespacemap插件可以很好的监测块中空间的使用情况,可当作full vacuum
操作的参考信息。
1 2 3 4 5 6 7 |
|