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

Commita9b05bd

Browse files
committed
Avoid O(N^2) overhead in repeated nocachegetattr calls when columns of
a tuple are being accessed via ExecEvalVar and the attcacheoff shortcutisn't usable (due to nulls and/or varlena columns). To do this, cacheDatums extracted from a tuple in the associated TupleTableSlot.Also some code cleanup in and around the TupleTable handling.Atsushi Ogawa with some kibitzing by Tom Lane.
1 parentd1022ce commita9b05bd

File tree

8 files changed

+361
-283
lines changed

8 files changed

+361
-283
lines changed

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

Lines changed: 184 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.96 2005/01/27 23:23:49 neilc Exp $
12+
* $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.97 2005/03/14 04:41:12 tgl Exp $
1313
*
1414
* NOTES
1515
* The old interface functions have been converted to macros
@@ -23,6 +23,7 @@
2323
#include"access/heapam.h"
2424
#include"access/tuptoaster.h"
2525
#include"catalog/pg_type.h"
26+
#include"executor/tuptable.h"
2627

2728

2829
/* ----------------------------------------------------------------
@@ -751,6 +752,7 @@ heap_deformtuple(HeapTuple tuple,
751752
char*nulls)
752753
{
753754
HeapTupleHeadertup=tuple->t_data;
755+
boolhasnulls=HeapTupleHasNulls(tuple);
754756
Form_pg_attribute*att=tupleDesc->attrs;
755757
inttdesc_natts=tupleDesc->natts;
756758
intnatts;/* number of atts to extract */
@@ -775,7 +777,9 @@ heap_deformtuple(HeapTuple tuple,
775777

776778
for (attnum=0;attnum<natts;attnum++)
777779
{
778-
if (HeapTupleHasNulls(tuple)&&att_isnull(attnum,bp))
780+
Form_pg_attributethisatt=att[attnum];
781+
782+
if (hasnulls&&att_isnull(attnum,bp))
779783
{
780784
values[attnum]= (Datum)0;
781785
nulls[attnum]='n';
@@ -785,21 +789,21 @@ heap_deformtuple(HeapTuple tuple,
785789

786790
nulls[attnum]=' ';
787791

788-
if (!slow&&att[attnum]->attcacheoff >=0)
789-
off=att[attnum]->attcacheoff;
792+
if (!slow&&thisatt->attcacheoff >=0)
793+
off=thisatt->attcacheoff;
790794
else
791795
{
792-
off=att_align(off,att[attnum]->attalign);
796+
off=att_align(off,thisatt->attalign);
793797

794798
if (!slow)
795-
att[attnum]->attcacheoff=off;
799+
thisatt->attcacheoff=off;
796800
}
797801

798-
values[attnum]=fetchatt(att[attnum],tp+off);
802+
values[attnum]=fetchatt(thisatt,tp+off);
799803

800-
off=att_addlength(off,att[attnum]->attlen,tp+off);
804+
off=att_addlength(off,thisatt->attlen,tp+off);
801805

802-
if (att[attnum]->attlen <=0)
806+
if (thisatt->attlen <=0)
803807
slow= true;/* can't use attcacheoff anymore */
804808
}
805809

@@ -814,6 +818,177 @@ heap_deformtuple(HeapTuple tuple,
814818
}
815819
}
816820

821+
/* ----------------
822+
*slot_deformtuple
823+
*
824+
*Given a TupleTableSlot, extract data into cache_values array
825+
*from the slot's tuple.
826+
*
827+
*This is essentially an incremental version of heap_deformtuple:
828+
*on each call we extract attributes up to the one needed, without
829+
*re-computing information about previously extracted attributes.
830+
*slot->cache_natts is the number of attributes already extracted.
831+
*
832+
*This only gets called from slot_getattr. Note that slot_getattr
833+
*must check for a null attribute since we don't create an array
834+
*of null indicators.
835+
* ----------------
836+
*/
837+
staticvoid
838+
slot_deformtuple(TupleTableSlot*slot,intnatts)
839+
{
840+
HeapTupletuple=slot->val;
841+
TupleDesctupleDesc=slot->ttc_tupleDescriptor;
842+
Datum*values=slot->cache_values;
843+
HeapTupleHeadertup=tuple->t_data;
844+
boolhasnulls=HeapTupleHasNulls(tuple);
845+
Form_pg_attribute*att=tupleDesc->attrs;
846+
intattnum;
847+
char*tp;/* ptr to tuple data */
848+
longoff;/* offset in tuple data */
849+
bits8*bp=tup->t_bits;/* ptr to null bitmask in tuple */
850+
boolslow;/* can we use/set attcacheoff? */
851+
852+
/*
853+
* Check whether the first call for this tuple, and initialize or
854+
* restore loop state.
855+
*/
856+
attnum=slot->cache_natts;
857+
if (attnum==0)
858+
{
859+
/* Start from the first attribute */
860+
off=0;
861+
slow= false;
862+
}
863+
else
864+
{
865+
/* Restore state from previous execution */
866+
off=slot->cache_off;
867+
slow=slot->cache_slow;
868+
}
869+
870+
tp= (char*)tup+tup->t_hoff;
871+
872+
for (;attnum<natts;attnum++)
873+
{
874+
Form_pg_attributethisatt=att[attnum];
875+
876+
if (hasnulls&&att_isnull(attnum,bp))
877+
{
878+
values[attnum]= (Datum)0;
879+
slow= true;/* can't use attcacheoff anymore */
880+
continue;
881+
}
882+
883+
if (!slow&&thisatt->attcacheoff >=0)
884+
off=thisatt->attcacheoff;
885+
else
886+
{
887+
off=att_align(off,thisatt->attalign);
888+
889+
if (!slow)
890+
thisatt->attcacheoff=off;
891+
}
892+
893+
values[attnum]=fetchatt(thisatt,tp+off);
894+
895+
off=att_addlength(off,thisatt->attlen,tp+off);
896+
897+
if (thisatt->attlen <=0)
898+
slow= true;/* can't use attcacheoff anymore */
899+
}
900+
901+
/*
902+
* Save state for next execution
903+
*/
904+
slot->cache_natts=attnum;
905+
slot->cache_off=off;
906+
slot->cache_slow=slow;
907+
}
908+
909+
/* --------------------------------
910+
*slot_getattr
911+
*
912+
*This function fetches an attribute of the slot's current tuple.
913+
*It is functionally equivalent to heap_getattr, but fetches of
914+
*multiple attributes of the same tuple will be optimized better,
915+
*because we avoid O(N^2) behavior from multiple calls of
916+
*nocachegetattr(), even when attcacheoff isn't usable.
917+
* --------------------------------
918+
*/
919+
Datum
920+
slot_getattr(TupleTableSlot*slot,intattnum,bool*isnull)
921+
{
922+
HeapTupletuple=slot->val;
923+
TupleDesctupleDesc=slot->ttc_tupleDescriptor;
924+
HeapTupleHeadertup;
925+
926+
/*
927+
* system attributes are handled by heap_getsysattr
928+
*/
929+
if (attnum <=0)
930+
returnheap_getsysattr(tuple,attnum,tupleDesc,isnull);
931+
932+
/*
933+
* check if attnum is out of range according to either the tupdesc
934+
* or the tuple itself; if so return NULL
935+
*/
936+
tup=tuple->t_data;
937+
938+
if (attnum>tup->t_natts||attnum>tupleDesc->natts)
939+
{
940+
*isnull= true;
941+
return (Datum)0;
942+
}
943+
944+
/*
945+
* check if target attribute is null
946+
*/
947+
if (HeapTupleHasNulls(tuple)&&att_isnull(attnum-1,tup->t_bits))
948+
{
949+
*isnull= true;
950+
return (Datum)0;
951+
}
952+
953+
/*
954+
* If the attribute's column has been dropped, we force a NULL
955+
* result. This case should not happen in normal use, but it could
956+
* happen if we are executing a plan cached before the column was
957+
* dropped.
958+
*/
959+
if (tupleDesc->attrs[attnum-1]->attisdropped)
960+
{
961+
*isnull= true;
962+
return (Datum)0;
963+
}
964+
965+
/*
966+
* If attribute wasn't already extracted, extract it and preceding
967+
* attributes.
968+
*/
969+
if (attnum>slot->cache_natts)
970+
{
971+
/*
972+
* If first time for this TupleTableSlot, allocate the cache
973+
* workspace. It must have the same lifetime as the slot, so allocate
974+
* it in the slot's own context. We size the array according to what
975+
* the tupdesc says, NOT the tuple.
976+
*/
977+
if (slot->cache_values==NULL)
978+
slot->cache_values= (Datum*)
979+
MemoryContextAlloc(slot->ttc_mcxt,
980+
tupleDesc->natts*sizeof(Datum));
981+
982+
slot_deformtuple(slot,attnum);
983+
}
984+
985+
/*
986+
* The result is acquired from cache_values array.
987+
*/
988+
*isnull= false;
989+
returnslot->cache_values[attnum-1];
990+
}
991+
817992
/* ----------------
818993
*heap_freetuple
819994
* ----------------

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

Lines changed: 5 additions & 5 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.47 2005/01/01 05:43:06 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.48 2005/03/14 04:41:12 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1197,9 +1197,9 @@ toast_fetch_datum(varattrib *attr)
11971197
/*
11981198
* Have a chunk, extract the sequence number and the data
11991199
*/
1200-
residx=DatumGetInt32(heap_getattr(ttup,2,toasttupDesc,&isnull));
1200+
residx=DatumGetInt32(fastgetattr(ttup,2,toasttupDesc,&isnull));
12011201
Assert(!isnull);
1202-
chunk=DatumGetPointer(heap_getattr(ttup,3,toasttupDesc,&isnull));
1202+
chunk=DatumGetPointer(fastgetattr(ttup,3,toasttupDesc,&isnull));
12031203
Assert(!isnull);
12041204
chunksize=VARATT_SIZE(chunk)-VARHDRSZ;
12051205

@@ -1372,9 +1372,9 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length)
13721372
/*
13731373
* Have a chunk, extract the sequence number and the data
13741374
*/
1375-
residx=DatumGetInt32(heap_getattr(ttup,2,toasttupDesc,&isnull));
1375+
residx=DatumGetInt32(fastgetattr(ttup,2,toasttupDesc,&isnull));
13761376
Assert(!isnull);
1377-
chunk=DatumGetPointer(heap_getattr(ttup,3,toasttupDesc,&isnull));
1377+
chunk=DatumGetPointer(fastgetattr(ttup,3,toasttupDesc,&isnull));
13781378
Assert(!isnull);
13791379
chunksize=VARATT_SIZE(chunk)-VARHDRSZ;
13801380

‎src/backend/executor/execJunk.c

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.46 2004/12/31 21:59:45 pgsql Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execJunk.c,v 1.47 2005/03/14 04:41:12 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -209,20 +209,13 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
209209
Datum*value,
210210
bool*isNull)
211211
{
212-
List*targetList;
213212
ListCell*t;
214-
AttrNumberresno;
215-
TupleDesctupType;
216-
HeapTupletuple;
217213

218214
/*
219-
*first look in the junkfilter's target list for an attribute with
215+
*Look in the junkfilter's target list for an attribute with
220216
* the given name
221217
*/
222-
resno=InvalidAttrNumber;
223-
targetList=junkfilter->jf_targetList;
224-
225-
foreach(t,targetList)
218+
foreach(t,junkfilter->jf_targetList)
226219
{
227220
TargetEntry*tle=lfirst(t);
228221
Resdom*resdom=tle->resdom;
@@ -231,26 +224,13 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
231224
(strcmp(resdom->resname,attrName)==0))
232225
{
233226
/* We found it ! */
234-
resno=resdom->resno;
235-
break;
227+
*value=slot_getattr(slot,resdom->resno,isNull);
228+
return true;
236229
}
237230
}
238231

239-
if (resno==InvalidAttrNumber)
240-
{
241-
/* Ooops! We couldn't find this attribute... */
242-
return false;
243-
}
244-
245-
/*
246-
* Now extract the attribute value from the tuple.
247-
*/
248-
tuple=slot->val;
249-
tupType=slot->ttc_tupleDescriptor;
250-
251-
*value=heap_getattr(tuple,resno,tupType,isNull);
252-
253-
return true;
232+
/* Ooops! We couldn't find this attribute... */
233+
return false;
254234
}
255235

256236
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp