Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8f2ea8b

Browse files
committed
Resurrect heap_deformtuple(), this time implemented as a singly nested
loop over the fields instead of a loop around heap_getattr. This isconsiderably faster (O(N) instead of O(N^2)) when there are nulls orvarlena fields, since those prevent use of attcacheoff. Replace loopsover heap_getattr with heap_deformtuple in situations where all or mostof the fields have to be fetched, such as printtup and tuptoaster.Profiling done more than a year ago shows that this should be a nicewin for situations involving many-column tables.
1 parentaf44cac commit8f2ea8b

File tree

8 files changed

+314
-208
lines changed

8 files changed

+314
-208
lines changed

‎src/backend/access/common/heaptuple.c

Lines changed: 166 additions & 114 deletions
Large diffs are not rendered by default.

‎src/backend/access/common/printtup.c

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.81 2004/05/26 04:41:03 neilc Exp $
12+
* $PostgreSQL: pgsql/src/backend/access/common/printtup.c,v 1.82 2004/06/04 20:35:21 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -65,6 +65,8 @@ typedef struct
6565
TupleDescattrinfo;/* The attr info we are set up for */
6666
intnattrs;
6767
PrinttupAttrInfo*myinfo;/* Cached info about each attr */
68+
Datum*values;/* preallocated space for deformtuple */
69+
char*nulls;
6870
}DR_printtup;
6971

7072
/* ----------------
@@ -103,6 +105,8 @@ printtup_create_DR(CommandDest dest, Portal portal)
103105
self->attrinfo=NULL;
104106
self->nattrs=0;
105107
self->myinfo=NULL;
108+
self->values=NULL;
109+
self->nulls=NULL;
106110

107111
return (DestReceiver*)self;
108112
}
@@ -243,15 +247,27 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
243247
int16*formats=myState->portal->formats;
244248
inti;
245249

250+
/* get rid of any old data */
246251
if (myState->myinfo)
247-
pfree(myState->myinfo);/* get rid of any old data */
252+
pfree(myState->myinfo);
248253
myState->myinfo=NULL;
254+
if (myState->values)
255+
pfree(myState->values);
256+
myState->values=NULL;
257+
if (myState->nulls)
258+
pfree(myState->nulls);
259+
myState->nulls=NULL;
260+
249261
myState->attrinfo=typeinfo;
250262
myState->nattrs=numAttrs;
251263
if (numAttrs <=0)
252264
return;
265+
253266
myState->myinfo= (PrinttupAttrInfo*)
254267
palloc0(numAttrs*sizeof(PrinttupAttrInfo));
268+
myState->values= (Datum*)palloc(numAttrs*sizeof(Datum));
269+
myState->nulls= (char*)palloc(numAttrs*sizeof(char));
270+
255271
for (i=0;i<numAttrs;i++)
256272
{
257273
PrinttupAttrInfo*thisState=myState->myinfo+i;
@@ -297,6 +313,11 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
297313
if (myState->attrinfo!=typeinfo||myState->nattrs!=natts)
298314
printtup_prepare_info(myState,typeinfo,natts);
299315

316+
/*
317+
* deconstruct the tuple (faster than a heap_getattr loop)
318+
*/
319+
heap_deformtuple(tuple,typeinfo,myState->values,myState->nulls);
320+
300321
/*
301322
* Prepare a DataRow message
302323
*/
@@ -310,12 +331,10 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
310331
for (i=0;i<natts;++i)
311332
{
312333
PrinttupAttrInfo*thisState=myState->myinfo+i;
313-
Datumorigattr,
334+
Datumorigattr=myState->values[i],
314335
attr;
315-
boolisnull;
316336

317-
origattr=heap_getattr(tuple,i+1,typeinfo,&isnull);
318-
if (isnull)
337+
if (myState->nulls[i]=='n')
319338
{
320339
pq_sendint(&buf,-1,4);
321340
continue;
@@ -383,6 +402,11 @@ printtup_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
383402
if (myState->attrinfo!=typeinfo||myState->nattrs!=natts)
384403
printtup_prepare_info(myState,typeinfo,natts);
385404

405+
/*
406+
* deconstruct the tuple (faster than a heap_getattr loop)
407+
*/
408+
heap_deformtuple(tuple,typeinfo,myState->values,myState->nulls);
409+
386410
/*
387411
* tell the frontend to expect new tuple data (in ASCII style)
388412
*/
@@ -395,7 +419,7 @@ printtup_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
395419
k=1 <<7;
396420
for (i=0;i<natts;++i)
397421
{
398-
if (!heap_attisnull(tuple,i+1))
422+
if (myState->nulls[i]!='n')
399423
j |=k;/* set bit if not null */
400424
k >>=1;
401425
if (k==0)/* end of byte? */
@@ -414,13 +438,11 @@ printtup_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
414438
for (i=0;i<natts;++i)
415439
{
416440
PrinttupAttrInfo*thisState=myState->myinfo+i;
417-
Datumorigattr,
441+
Datumorigattr=myState->values[i],
418442
attr;
419-
boolisnull;
420443
char*outputstr;
421444

422-
origattr=heap_getattr(tuple,i+1,typeinfo,&isnull);
423-
if (isnull)
445+
if (myState->nulls[i]=='n')
424446
continue;
425447

426448
Assert(thisState->format==0);
@@ -461,6 +483,13 @@ printtup_shutdown(DestReceiver *self)
461483
if (myState->myinfo)
462484
pfree(myState->myinfo);
463485
myState->myinfo=NULL;
486+
if (myState->values)
487+
pfree(myState->values);
488+
myState->values=NULL;
489+
if (myState->nulls)
490+
pfree(myState->nulls);
491+
myState->nulls=NULL;
492+
464493
myState->attrinfo=NULL;
465494
}
466495

@@ -587,6 +616,11 @@ printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
587616
if (myState->attrinfo!=typeinfo||myState->nattrs!=natts)
588617
printtup_prepare_info(myState,typeinfo,natts);
589618

619+
/*
620+
* deconstruct the tuple (faster than a heap_getattr loop)
621+
*/
622+
heap_deformtuple(tuple,typeinfo,myState->values,myState->nulls);
623+
590624
/*
591625
* tell the frontend to expect new tuple data (in binary style)
592626
*/
@@ -599,7 +633,7 @@ printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
599633
k=1 <<7;
600634
for (i=0;i<natts;++i)
601635
{
602-
if (!heap_attisnull(tuple,i+1))
636+
if (myState->nulls[i]!='n')
603637
j |=k;/* set bit if not null */
604638
k >>=1;
605639
if (k==0)/* end of byte? */
@@ -618,13 +652,11 @@ printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
618652
for (i=0;i<natts;++i)
619653
{
620654
PrinttupAttrInfo*thisState=myState->myinfo+i;
621-
Datumorigattr,
655+
Datumorigattr=myState->values[i],
622656
attr;
623-
boolisnull;
624657
bytea*outputbytes;
625658

626-
origattr=heap_getattr(tuple,i+1,typeinfo,&isnull);
627-
if (isnull)
659+
if (myState->nulls[i]=='n')
628660
continue;
629661

630662
Assert(thisState->format==1);

‎src/backend/access/heap/tuptoaster.c

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.41 2003/11/29 19:51:40 pgsql Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.42 2004/06/04 20:35:21 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -281,15 +281,26 @@ toast_delete(Relation rel, HeapTuple oldtup)
281281
Form_pg_attribute*att;
282282
intnumAttrs;
283283
inti;
284-
Datumvalue;
285-
boolisnull;
284+
Datumtoast_values[MaxHeapAttributeNumber];
285+
chartoast_nulls[MaxHeapAttributeNumber];
286286

287287
/*
288-
* Get the tuple descriptor, the number of and attribute descriptors.
288+
* Get the tuple descriptor and break down the tuple into fields.
289+
*
290+
* NOTE: it's debatable whether to use heap_deformtuple() here or
291+
* just heap_getattr() only the varlena columns. The latter could
292+
* win if there are few varlena columns and many non-varlena ones.
293+
* However, heap_deformtuple costs only O(N) while the heap_getattr
294+
* way would cost O(N^2) if there are many varlena columns, so it
295+
* seems better to err on the side of linear cost. (We won't even
296+
* be here unless there's at least one varlena column, by the way.)
289297
*/
290298
tupleDesc=rel->rd_att;
291-
numAttrs=tupleDesc->natts;
292299
att=tupleDesc->attrs;
300+
numAttrs=tupleDesc->natts;
301+
302+
Assert(numAttrs <=MaxHeapAttributeNumber);
303+
heap_deformtuple(oldtup,tupleDesc,toast_values,toast_nulls);
293304

294305
/*
295306
* Check for external stored attributes and delete them from the
@@ -299,8 +310,9 @@ toast_delete(Relation rel, HeapTuple oldtup)
299310
{
300311
if (att[i]->attlen==-1)
301312
{
302-
value=heap_getattr(oldtup,i+1,tupleDesc,&isnull);
303-
if (!isnull&&VARATT_IS_EXTERNAL(value))
313+
Datumvalue=toast_values[i];
314+
315+
if (toast_nulls[i]!='n'&&VARATT_IS_EXTERNAL(value))
304316
toast_delete_datum(rel,value);
305317
}
306318
}
@@ -321,8 +333,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
321333
Form_pg_attribute*att;
322334
intnumAttrs;
323335
inti;
324-
boolold_isnull;
325-
boolnew_isnull;
326336

327337
boolneed_change= false;
328338
boolneed_free= false;
@@ -333,18 +343,24 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
333343

334344
chartoast_action[MaxHeapAttributeNumber];
335345
chartoast_nulls[MaxHeapAttributeNumber];
346+
chartoast_oldnulls[MaxHeapAttributeNumber];
336347
Datumtoast_values[MaxHeapAttributeNumber];
348+
Datumtoast_oldvalues[MaxHeapAttributeNumber];
337349
int32toast_sizes[MaxHeapAttributeNumber];
338350
booltoast_free[MaxHeapAttributeNumber];
339351
booltoast_delold[MaxHeapAttributeNumber];
340352

341353
/*
342-
* Get the tuple descriptor, the number of and attribute descriptors
343-
* and the location of the tuple values.
354+
* Get the tuple descriptor and break down the tuple(s) into fields.
344355
*/
345356
tupleDesc=rel->rd_att;
346-
numAttrs=tupleDesc->natts;
347357
att=tupleDesc->attrs;
358+
numAttrs=tupleDesc->natts;
359+
360+
Assert(numAttrs <=MaxHeapAttributeNumber);
361+
heap_deformtuple(newtup,tupleDesc,toast_values,toast_nulls);
362+
if (oldtup!=NULL)
363+
heap_deformtuple(oldtup,tupleDesc,toast_oldvalues,toast_oldnulls);
348364

349365
/* ----------
350366
* Then collect information about the values given
@@ -353,12 +369,15 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
353369
*' 'default handling
354370
*'p'already processed --- don't touch it
355371
*'x'incompressible, but OK to move off
372+
*
373+
* NOTE: toast_sizes[i] is only made valid for varlena attributes with
374+
*toast_action[i] different from 'p'.
356375
* ----------
357376
*/
358377
memset(toast_action,' ',numAttrs*sizeof(char));
359-
memset(toast_nulls,' ',numAttrs*sizeof(char));
360378
memset(toast_free,0,numAttrs*sizeof(bool));
361379
memset(toast_delold,0,numAttrs*sizeof(bool));
380+
362381
for (i=0;i<numAttrs;i++)
363382
{
364383
varattrib*old_value;
@@ -369,27 +388,24 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
369388
/*
370389
* For UPDATE get the old and new values of this attribute
371390
*/
372-
old_value= (varattrib*)DatumGetPointer(
373-
heap_getattr(oldtup,i+1,tupleDesc,&old_isnull));
374-
toast_values[i]=
375-
heap_getattr(newtup,i+1,tupleDesc,&new_isnull);
391+
old_value= (varattrib*)DatumGetPointer(toast_oldvalues[i]);
376392
new_value= (varattrib*)DatumGetPointer(toast_values[i]);
377393

378394
/*
379395
* If the old value is an external stored one, check if it has
380396
* changed so we have to delete it later.
381397
*/
382-
if (!old_isnull&&att[i]->attlen==-1&&
398+
if (att[i]->attlen==-1&&toast_oldnulls[i]!='n'&&
383399
VARATT_IS_EXTERNAL(old_value))
384400
{
385-
if (new_isnull|| !VARATT_IS_EXTERNAL(new_value)||
401+
if (toast_nulls[i]=='n'|| !VARATT_IS_EXTERNAL(new_value)||
386402
old_value->va_content.va_external.va_valueid!=
387403
new_value->va_content.va_external.va_valueid||
388404
old_value->va_content.va_external.va_toastrelid!=
389405
new_value->va_content.va_external.va_toastrelid)
390406
{
391407
/*
392-
* The old externalstore value isn't needed any more
408+
* The old externalstored value isn't needed any more
393409
* after the update
394410
*/
395411
toast_delold[i]= true;
@@ -413,23 +429,21 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
413429
/*
414430
* For INSERT simply get the new value
415431
*/
416-
toast_values[i]=
417-
heap_getattr(newtup,i+1,tupleDesc,&new_isnull);
432+
new_value= (varattrib*)DatumGetPointer(toast_values[i]);
418433
}
419434

420435
/*
421436
* Handle NULL attributes
422437
*/
423-
if (new_isnull)
438+
if (toast_nulls[i]=='n')
424439
{
425440
toast_action[i]='p';
426-
toast_nulls[i]='n';
427441
has_nulls= true;
428442
continue;
429443
}
430444

431445
/*
432-
* Now look atvarsize attributes
446+
* Now look atvarlena attributes
433447
*/
434448
if (att[i]->attlen==-1)
435449
{
@@ -461,10 +475,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
461475
else
462476
{
463477
/*
464-
* Not avariable size attribute, plain storage always
478+
* Not avarlena attribute, plain storage always
465479
*/
466480
toast_action[i]='p';
467-
toast_sizes[i]=att[i]->attlen;
468481
}
469482
}
470483

@@ -768,8 +781,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup)
768781
if (need_delold)
769782
for (i=0;i<numAttrs;i++)
770783
if (toast_delold[i])
771-
toast_delete_datum(rel,
772-
heap_getattr(oldtup,i+1,tupleDesc,&old_isnull));
784+
toast_delete_datum(rel,toast_oldvalues[i]);
773785
}
774786

775787

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp