当前位置:网站首页>PostgreSQL source code (58) tuple splicing heap_ form_ Tuple analysis
PostgreSQL source code (58) tuple splicing heap_ form_ Tuple analysis
2022-07-01 23:28:00 【mingjie73】
edition :14
relevant :
《Postgresql Source code (51) Variable length type implementation (valena.c)》
《Postgresql Source code (56) Extensible type analysis ExpandedObject/ExpandedRecord》
2 background
- PG There are two forms of representation of the metagroup :expanded Format ( Easy to calculate ) and flatten Format ( Easy to save )
- above 《Postgresql Source code (56) Extensible type analysis ExpandedObject/ExpandedRecord》 The extended format of tuples is described in
- This article introduces the more general of tuples flatten Format HeapTupleData
- expanded Format and flatten Formats can be converted to each other (flatten_into A function pointer , Reference resources Postgresql Source code (56))
typedef struct HeapTupleData
{
uint32 t_len; /* length of *t_data */
ItemPointerData t_self; /* SelfItemPointer */
Oid t_tableOid; /* table the tuple came from */
HeapTupleHeader t_data; /* -> tuple header and data */
} HeapTupleData;
- t_len Look at , This is an obvious 4B Head lengthening structure ( Reference resources 《Postgresql Source code (51) Variable length type implementation (valena.c)》), Variable length type uses 4B Head follows PG Internal agreement .
3 HeapTuple Constructor for heap_form_tuple
HeapTuple The structure is heap_form_tuple Splicing in function , The following article focuses on the analysis of this function :
Inserted here 5 Take column data as an example : Three fixed lengths 、 Second, it becomes longer
drop table t21;
create table t21(i1 int, v10 varchar(10), n1 numeric, c2 char(2), t1 text);
insert into t21 values (1, 'mylen=7', 5.5, '22', 'hi12345');
3.1 heap_form_tuple Enter the reference
Constructors heap_form_tuple
HeapTuple
heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Note that the input parameter is a tuple descriptor 、 An array of values 、isnull Array , The value array contains int Value or datum Data pointer
(gdb) p *tupleDescriptor
$9 = {natts = 5, tdtypeid = 2249, tdtypmod = -1, tdrefcount = -1, constr = 0x0, attrs = 0x199ce90}
(gdb) p values[0]
$11 = 1 : int Value
(gdb) p values[1]
$12 = 27157600 : datum Data pointer
(gdb) p values[2]
$13 = 27153160 : datum Data pointer
(gdb) p values[3]
$14 = 27158432 : datum Data pointer
(gdb) p values[4]
$15 = 27154592 : datum Data pointer
(gdb) p isnull[0]
$17 = false
(gdb) p isnull[1]
$18 = false
(gdb) p isnull[2]
$19 = false
(gdb) p isnull[3]
$20 = false
(gdb) p isnull[4]
$21 = false
3.2 heap_form_tuple Execute the process
- Be careful :hoff The position is HeapTupleHeaderData In the future, it can be shifted to data
- Be careful :tuple->t_data The position is HeapTupleData How much can you offset back to HeapTupleHeaderData The position of the head
- The memory structure is :
HeapTupleData
+HeapTupleHeaderData
+data
heap_form_tuple
...
len = offsetof(HeapTupleHeaderData, t_bits) : Calculate the size of the head len = 23,t_bits Is a flexible array pointer
hoff = len = MAXALIGN(len); : alignment hoff = len = 24
data_len = heap_compute_data_size(...) : See 3.3, common data_len = 30 byte
len += data_len; : len = 24 + 30 = 54
tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len) : apply HeapTupleData + HeapTupleHeaderData + data 30 byte
tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE)
: t_data Pointing to HeapTupleData after ,HeapTupleHeaderData The position of the head
...
// To configure tuple Value
...
heap_fill_tuple : Start adding data according to the data type , see 3.4
3.3 heap_compute_data_size
Calculate the data length heap_compute_data_size, Already below SQL For example
drop table t21;
create table t21(i1 int, v10 varchar(10), n1 numeric, c2 char(2), t1 text);
insert into t21 values (1, 'mylen=7', 5.5, '22', 'hi12345');
Function handles each column separately , The main processing logic takes three branches :
3.3.1 The entry logic of three branches
Branch one : atti->attlen == -1
And atti->attstorage != 'p'
And Now it's 4B head And The data is very short and can be changed into 1B head
Branch two : atti->attlen == -1
And Now it's 1B_E head And 1B_E yes RO type VARTAG_EXPANDED_RO
Branch three : Other situations
if (ATT_IS_PACKABLE(atti) &&
VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
{
/*
* we're anticipating converting to a short varlena header, so
* adjust length and don't count any alignment
*/
data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
}
else if (atti->attlen == -1 &&
VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val)))
{
/*
* we want to flatten the expanded value so that the constructed
* tuple doesn't depend on it
*/
data_length = att_align_nominal(data_length, atti->attalign);
data_length += EOH_get_flat_size(DatumGetEOHP(val));
}
else
{
data_length = att_align_datum(data_length, atti->attalign,
atti->attlen, val);
data_length = att_addlength_datum(data_length, atti->attlen,
val);
}
For five columns of test data
int type : Take branch three ( length 4)
(gdb) p atti->attlen
$30 = 4
(gdb) p atti->attstorage
$31 = 112 'p'
Calculation process
// First step : alignment data_length=0, After alignment, it is still 0
data_length = att_align_datum(data_length, atti->attalign,
atti->attlen, val);
// The second step : Plus length atti->attlen,data_length=4
data_length = att_addlength_datum(data_length, atti->attlen,
val);
Increase in length 4
varchar type : Take a branch ( length 8)
(gdb) p atti->attlen
$38 = -1
(gdb) p atti->attstorage
$39 = 120 'x'
Calculation process
// can 1B It can be installed , Behind the 4B Turn into 1B head , Here by 1B Calculate the length
data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val))
Increase in length 8
numeric type : Take a branch ( length 7)
char type : Take a branch ( length 3)
1B Add yourself to your head 2 Bytes , Three bytes in total
text type : Take a branch ( length 8)
1B Add yourself to your head 7 Bytes , altogether 8 byte
3.4 heap_fill_tuple
heap_fill_tuple Call... For each column fill_val Fill in data
heap_fill_tuple
for (i = 0; i < numberOfAttributes; i++)
fill_val(...)
fill_val There are more branches of , For each column, go to the following 4 Branches to handle
if (att->attbyval)
{
/* pass-by-value */
data = (char *) att_align_nominal(data, att->attalign);
store_att_byval(data, datum, att->attlen);
data_length = att->attlen;
}
else if (att->attlen == -1)
{
/* varlena */
Pointer val = DatumGetPointer(datum);
*infomask |= HEAP_HASVARWIDTH;
if (VARATT_IS_EXTERNAL(val))
{
if (VARATT_IS_EXTERNAL_EXPANDED(val))
{
/*
* we want to flatten the expanded value so that the
* constructed tuple doesn't depend on it
*/
ExpandedObjectHeader *eoh = DatumGetEOHP(datum);
data = (char *) att_align_nominal(data,
att->attalign);
data_length = EOH_get_flat_size(eoh);
EOH_flatten_into(eoh, data, data_length);
}
else
{
*infomask |= HEAP_HASEXTERNAL;
/* no alignment, since it's short by definition */
data_length = VARSIZE_EXTERNAL(val);
memcpy(data, val, data_length);
}
}
else if (VARATT_IS_SHORT(val))
{
/* no alignment for short varlenas */
data_length = VARSIZE_SHORT(val);
memcpy(data, val, data_length);
}
else if (VARLENA_ATT_IS_PACKABLE(att) &&
VARATT_CAN_MAKE_SHORT(val))
{
/* convert to short varlena -- no alignment */
data_length = VARATT_CONVERTED_SHORT_SIZE(val);
SET_VARSIZE_SHORT(data, data_length);
memcpy(data + 1, VARDATA(val), data_length - 1);
}
else
{
/* full 4-byte header varlena */
data = (char *) att_align_nominal(data,
att->attalign);
data_length = VARSIZE(val);
memcpy(data, val, data_length);
}
}
else if (att->attlen == -2)
{
/* cstring ... never needs alignment */
*infomask |= HEAP_HASVARWIDTH;
Assert(att->attalign == TYPALIGN_CHAR);
data_length = strlen(DatumGetCString(datum)) + 1;
memcpy(data, DatumGetPointer(datum), data_length);
}
else
{
/* fixed-length pass-by-reference */
data = (char *) att_align_nominal(data, att->attalign);
Assert(att->attlen > 0);
data_length = att->attlen;
memcpy(data, DatumGetPointer(datum), data_length);
}
Branch :
att->attbyval == true
Values are passed directly , Just assign values directlyatt->attlen == -1
Variable length head type , To go valena Press 4B、1B、1B_E Deal with... Separatelyatt->attlen == -2
Direct copy cstring type- other : Direct copy
For five columns of test data
int type : Take a branch : Value copy
The data transferred is stored in the stack memory , Direct assignment
varchar type : Take branch two : data 4B Convert to 1B Post memory copy
The data is small enough , Don't have to 4B Header storage , Convert to 1B Copy the header after saving
numeric type : Take branch two : data 4B Convert to 1B Post memory copy
The data is small enough , Don't have to 4B Header storage , Convert to 1B Copy the header after saving
char type : Take branch two : data 4B Convert to 1B Post memory copy
The data is small enough , Don't have to 4B Header storage , Convert to 1B Copy the header after saving
text type : Take branch two : data 4B Convert to 1B Post memory copy
The data is small enough , Don't have to 4B Header storage , Convert to 1B Copy the header after saving
边栏推荐
猜你喜欢
2021 RoboCom 世界机器人开发者大赛-本科组初赛
建模和影视后期有什么关联?
字典、哈希表、数组的概念
【小程序】通过scroll-view组件实现左右【滑动】列表
Redis data types and application scenarios
2022年最佳智能家居开源系统:Alexa、Home Assistant、HomeKit生态系统介绍
Redis AOF日志
What is mosaic?
How to display real-time 2D map after rviz is opened
Notes to problems - file /usr/share/mysql/charsets/readme from install of mysql-server-5.1.73-1 glibc23.x86_ 64 c
随机推荐
为什么PHP叫超文本预处理器
Why is PHP called hypertext preprocessor
Stm32f030f4 drives tim1637 nixie tube chip
Daily three questions 6.30
De PIP. Interne. CLI. Main Import main modulenotfounderror: No module named 'PIP'
每日三题 6.29
距离度量 —— 汉明距离(Hamming Distance)
Switch to software testing, knowing these four points is enough!
The best smart home open source system in 2022: introduction to Alexa, home assistant and homekit ecosystem
Istio, ebpf and rsocket Broker: in depth study of service grid
Redis~02 cache: how to ensure data consistency in MySQL and redis when updating data?
云信小课堂 | IM及音视频中常见的认知误区
Create Ca and issue certificate through go language
The online beggar function of Japanese shopping websites
Linux基础 —— CentOS7 离线安装 MySQL
"35 years old, the boss of the company, with a monthly salary of 20000, give away takeout": the times abandoned you, not even saying goodbye
CKS CKA ckad change terminal to remote desktop
Practical application and extension of plain framework
plain framework的实际应用和扩展
Three development trends of enterprise application from the perspective of the third technological revolution