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

Commit80b9e9c

Browse files
committed
Improve performance of index-only scans with many index columns.
StoreIndexTuple was a loop over index_getattr, which is O(N^2)if the index columns are variable-width, and the performanceimpact is already quite visible at ten columns. The obviousmove is to replace that with a call to index_deform_tuple ...but that's *also* a loop over index_getattr. Improve it tobe essentially a clone of heap_deform_tuple.(There are a few other places that loop over all index columnswith index_getattr, and perhaps should be changed likewise,but most of them don't seem performance-critical. Anyway, therest would mostly only be interested in the index key columns,which there aren't likely to be so many of. Wide index tuplesare a new thing with INCLUDE.)Konstantin KnizhnikDiscussion:https://postgr.es/m/e06b2d27-04fc-5c0e-bb8c-ecd72aa24959@postgrespro.ru
1 parent78b408a commit80b9e9c

File tree

2 files changed

+72
-17
lines changed

2 files changed

+72
-17
lines changed

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

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,19 +418,80 @@ nocache_index_getattr(IndexTuple tup,
418418
*
419419
* The caller must allocate sufficient storage for the output arrays.
420420
* (INDEX_MAX_KEYS entries should be enough.)
421+
*
422+
* This is nearly the same as heap_deform_tuple(), but for IndexTuples.
423+
* One difference is that the tuple should never have any missing columns.
421424
*/
422425
void
423426
index_deform_tuple(IndexTupletup,TupleDesctupleDescriptor,
424427
Datum*values,bool*isnull)
425428
{
426-
inti;
429+
inthasnulls=IndexTupleHasNulls(tup);
430+
intnatts=tupleDescriptor->natts;/* number of atts to extract */
431+
intattnum;
432+
char*tp;/* ptr to tuple data */
433+
intoff;/* offset in tuple data */
434+
bits8*bp;/* ptr to null bitmap in tuple */
435+
boolslow= false;/* can we use/set attcacheoff? */
427436

428437
/* Assert to protect callers who allocate fixed-size arrays */
429-
Assert(tupleDescriptor->natts <=INDEX_MAX_KEYS);
438+
Assert(natts <=INDEX_MAX_KEYS);
439+
440+
/* XXX "knows" t_bits are just after fixed tuple header! */
441+
bp= (bits8*) ((char*)tup+sizeof(IndexTupleData));
430442

431-
for (i=0;i<tupleDescriptor->natts;i++)
443+
tp= (char*)tup+IndexInfoFindDataOffset(tup->t_info);
444+
off=0;
445+
446+
for (attnum=0;attnum<natts;attnum++)
432447
{
433-
values[i]=index_getattr(tup,i+1,tupleDescriptor,&isnull[i]);
448+
Form_pg_attributethisatt=TupleDescAttr(tupleDescriptor,attnum);
449+
450+
if (hasnulls&&att_isnull(attnum,bp))
451+
{
452+
values[attnum]= (Datum)0;
453+
isnull[attnum]= true;
454+
slow= true;/* can't use attcacheoff anymore */
455+
continue;
456+
}
457+
458+
isnull[attnum]= false;
459+
460+
if (!slow&&thisatt->attcacheoff >=0)
461+
off=thisatt->attcacheoff;
462+
elseif (thisatt->attlen==-1)
463+
{
464+
/*
465+
* We can only cache the offset for a varlena attribute if the
466+
* offset is already suitably aligned, so that there would be no
467+
* pad bytes in any case: then the offset will be valid for either
468+
* an aligned or unaligned value.
469+
*/
470+
if (!slow&&
471+
off==att_align_nominal(off,thisatt->attalign))
472+
thisatt->attcacheoff=off;
473+
else
474+
{
475+
off=att_align_pointer(off,thisatt->attalign,-1,
476+
tp+off);
477+
slow= true;
478+
}
479+
}
480+
else
481+
{
482+
/* not varlena, so safe to use att_align_nominal */
483+
off=att_align_nominal(off,thisatt->attalign);
484+
485+
if (!slow)
486+
thisatt->attcacheoff=off;
487+
}
488+
489+
values[attnum]=fetchatt(thisatt,tp+off);
490+
491+
off=att_addlength_pointer(off,thisatt->attlen,tp+off);
492+
493+
if (thisatt->attlen <=0)
494+
slow= true;/* can't use attcacheoff anymore */
434495
}
435496
}
436497

‎src/backend/executor/nodeIndexonlyscan.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -269,23 +269,17 @@ IndexOnlyNext(IndexOnlyScanState *node)
269269
staticvoid
270270
StoreIndexTuple(TupleTableSlot*slot,IndexTupleitup,TupleDescitupdesc)
271271
{
272-
intnindexatts=itupdesc->natts;
273-
Datum*values=slot->tts_values;
274-
bool*isnull=slot->tts_isnull;
275-
inti;
276-
277272
/*
278-
* Note: we must use the tupdesc supplied by the AM inindex_getattr, not
279-
* the slot's tupdesc, in case the latter has different datatypes (this
280-
* happens for btree name_ops in particular). They'd better have the same
281-
* number of columns though, as well as being datatype-compatible which is
282-
* something we can't so easily check.
273+
* Note: we must use the tupdesc supplied by the AM inindex_deform_tuple,
274+
*notthe slot's tupdesc, in case the latter has different datatypes
275+
*(thishappens for btree name_ops in particular). They'd better have
276+
*the samenumber of columns though, as well as being datatype-compatible
277+
*which issomething we can't so easily check.
283278
*/
284-
Assert(slot->tts_tupleDescriptor->natts==nindexatts);
279+
Assert(slot->tts_tupleDescriptor->natts==itupdesc->natts);
285280

286281
ExecClearTuple(slot);
287-
for (i=0;i<nindexatts;i++)
288-
values[i]=index_getattr(itup,i+1,itupdesc,&isnull[i]);
282+
index_deform_tuple(itup,itupdesc,slot->tts_values,slot->tts_isnull);
289283
ExecStoreVirtualTuple(slot);
290284
}
291285

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp