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

Commite0ece2a

Browse files
committed
TupleHashTable: store additional data along with tuple.
Previously, the caller needed to allocate the memory and theTupleHashTable would store a pointer to it. That wastes space for thepalloc overhead as well as the size of the pointer itself.Now, the TupleHashTable relies on the caller to correctly specify theadditionalsize, and allocates that amount of space. The caller canthen request a pointer into that space.Discussion:https://postgr.es/m/b9cbf0219a9859dc8d240311643ff4362fd9602c.camel@j-davis.comReviewed-by: Heikki Linnakangas
1 parent34c6e65 commite0ece2a

File tree

6 files changed

+78
-31
lines changed

6 files changed

+78
-31
lines changed

‎src/backend/executor/execGrouping.c

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
#include"miscadmin.h"
2121
#include"utils/lsyscache.h"
2222

23+
typedefstructTupleHashEntryData
24+
{
25+
MinimalTuplefirstTuple;/* copy of first tuple in this group */
26+
uint32status;/* hash status */
27+
uint32hash;/* hash value (cached) */
28+
}TupleHashEntryData;
29+
2330
staticintTupleHashTableMatch(structtuplehash_hash*tb,constMinimalTupletuple1,constMinimalTupletuple2);
2431
staticinlineuint32TupleHashTableHash_internal(structtuplehash_hash*tb,
2532
constMinimalTupletuple);
@@ -196,6 +203,7 @@ BuildTupleHashTable(PlanState *parent,
196203
hashtable->tab_collations=collations;
197204
hashtable->tablecxt=tablecxt;
198205
hashtable->tempcxt=tempcxt;
206+
hashtable->additionalsize=additionalsize;
199207
hashtable->tableslot=NULL;/* will be made on first lookup */
200208
hashtable->inputslot=NULL;
201209
hashtable->in_hash_expr=NULL;
@@ -273,6 +281,15 @@ ResetTupleHashTable(TupleHashTable hashtable)
273281
tuplehash_reset(hashtable->hashtab);
274282
}
275283

284+
/*
285+
* Return size of the hash bucket. Useful for estimating memory usage.
286+
*/
287+
size_t
288+
TupleHashEntrySize(void)
289+
{
290+
returnsizeof(TupleHashEntryData);
291+
}
292+
276293
/*
277294
* Find or create a hashtable entry for the tuple group containing the
278295
* given tuple. The tuple must be the same type as the hashtable entries.
@@ -339,6 +356,24 @@ TupleHashTableHash(TupleHashTable hashtable, TupleTableSlot *slot)
339356
returnhash;
340357
}
341358

359+
MinimalTuple
360+
TupleHashEntryGetTuple(TupleHashEntryentry)
361+
{
362+
returnentry->firstTuple;
363+
}
364+
365+
/*
366+
* Get a pointer into the additional space allocated for this entry. The
367+
* amount of space available is the additionalsize specified to
368+
* BuildTupleHashTable(). If additionalsize was specified as zero, no
369+
* additional space is available and this function should not be called.
370+
*/
371+
void*
372+
TupleHashEntryGetAdditional(TupleHashEntryentry)
373+
{
374+
return (char*)entry->firstTuple+MAXALIGN(entry->firstTuple->t_len);
375+
}
376+
342377
/*
343378
* A variant of LookupTupleHashEntry for callers that have already computed
344379
* the hash value.
@@ -477,13 +512,31 @@ LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot,
477512
}
478513
else
479514
{
515+
MinimalTuplefirstTuple;
516+
size_ttotalsize;/* including alignment and additionalsize */
517+
480518
/* created new entry */
481519
*isnew= true;
482520
/* zero caller data */
483-
entry->additional=NULL;
484521
MemoryContextSwitchTo(hashtable->tablecxt);
522+
485523
/* Copy the first tuple into the table context */
486-
entry->firstTuple=ExecCopySlotMinimalTuple(slot);
524+
firstTuple=ExecCopySlotMinimalTuple(slot);
525+
526+
/*
527+
* Allocate additional space right after the MinimalTuple of size
528+
* additionalsize. The caller can get a pointer to this data with
529+
* TupleHashEntryGetAdditional(), and store arbitrary data there.
530+
*
531+
* This avoids the need to store an extra pointer or allocate an
532+
* additional chunk, which would waste memory.
533+
*/
534+
totalsize=MAXALIGN(firstTuple->t_len)+hashtable->additionalsize;
535+
firstTuple=repalloc(firstTuple,totalsize);
536+
memset((char*)firstTuple+firstTuple->t_len,0,
537+
totalsize-firstTuple->t_len);
538+
539+
entry->firstTuple=firstTuple;
487540
}
488541
}
489542
else

‎src/backend/executor/nodeAgg.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,7 +1713,7 @@ hash_agg_entry_size(int numTrans, Size tupleWidth, Size transitionSpace)
17131713
transitionChunkSize=0;
17141714

17151715
return
1716-
sizeof(TupleHashEntryData)+
1716+
TupleHashEntrySize()+
17171717
tupleChunkSize+
17181718
pergroupChunkSize+
17191719
transitionChunkSize;
@@ -1954,7 +1954,7 @@ hash_agg_update_metrics(AggState *aggstate, bool from_tape, int npartitions)
19541954
if (aggstate->hash_ngroups_current>0)
19551955
{
19561956
aggstate->hashentrysize=
1957-
sizeof(TupleHashEntryData)+
1957+
TupleHashEntrySize()+
19581958
(hashkey_mem / (double)aggstate->hash_ngroups_current);
19591959
}
19601960
}
@@ -2055,11 +2055,7 @@ initialize_hash_entry(AggState *aggstate, TupleHashTable hashtable,
20552055
if (aggstate->numtrans==0)
20562056
return;
20572057

2058-
pergroup= (AggStatePerGroup)
2059-
MemoryContextAlloc(hashtable->tablecxt,
2060-
sizeof(AggStatePerGroupData)*aggstate->numtrans);
2061-
2062-
entry->additional=pergroup;
2058+
pergroup= (AggStatePerGroup)TupleHashEntryGetAdditional(entry);
20632059

20642060
/*
20652061
* Initialize aggregates for new tuple group, lookup_hash_entries()
@@ -2123,7 +2119,7 @@ lookup_hash_entries(AggState *aggstate)
21232119
{
21242120
if (isnew)
21252121
initialize_hash_entry(aggstate,hashtable,entry);
2126-
pergroup[setno]=entry->additional;
2122+
pergroup[setno]=TupleHashEntryGetAdditional(entry);
21272123
}
21282124
else
21292125
{
@@ -2681,7 +2677,7 @@ agg_refill_hash_table(AggState *aggstate)
26812677
{
26822678
if (isnew)
26832679
initialize_hash_entry(aggstate,perhash->hashtable,entry);
2684-
aggstate->hash_pergroup[batch->setno]=entry->additional;
2680+
aggstate->hash_pergroup[batch->setno]=TupleHashEntryGetAdditional(entry);
26852681
advance_aggregates(aggstate);
26862682
}
26872683
else
@@ -2773,7 +2769,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate)
27732769
ExprContext*econtext;
27742770
AggStatePerAggperagg;
27752771
AggStatePerGrouppergroup;
2776-
TupleHashEntryData*entry;
2772+
TupleHashEntryentry;
27772773
TupleTableSlot*firstSlot;
27782774
TupleTableSlot*result;
27792775
AggStatePerHashperhash;
@@ -2845,7 +2841,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate)
28452841
* Transform representative tuple back into one with the right
28462842
* columns.
28472843
*/
2848-
ExecStoreMinimalTuple(entry->firstTuple,hashslot, false);
2844+
ExecStoreMinimalTuple(TupleHashEntryGetTuple(entry),hashslot, false);
28492845
slot_getallattrs(hashslot);
28502846

28512847
ExecClearTuple(firstSlot);
@@ -2861,7 +2857,7 @@ agg_retrieve_hash_table_in_memory(AggState *aggstate)
28612857
}
28622858
ExecStoreVirtualTuple(firstSlot);
28632859

2864-
pergroup= (AggStatePerGroup)entry->additional;
2860+
pergroup= (AggStatePerGroup)TupleHashEntryGetAdditional(entry);
28652861

28662862
/*
28672863
* Use the representative input tuple for any references to

‎src/backend/executor/nodeSetOp.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ setop_fill_hash_table(SetOpState *setopstate)
425425
{
426426
TupleTableSlot*outerslot;
427427
TupleHashEntryData*entry;
428+
SetOpStatePerGrouppergroup;
428429
boolisnew;
429430

430431
outerslot=ExecProcNode(outerPlan);
@@ -437,16 +438,16 @@ setop_fill_hash_table(SetOpState *setopstate)
437438
outerslot,
438439
&isnew,NULL);
439440

441+
pergroup=TupleHashEntryGetAdditional(entry);
440442
/* If new tuple group, initialize counts to zero */
441443
if (isnew)
442444
{
443-
entry->additional= (SetOpStatePerGroup)
444-
MemoryContextAllocZero(setopstate->hashtable->tablecxt,
445-
sizeof(SetOpStatePerGroupData));
445+
pergroup->numLeft=0;
446+
pergroup->numRight=0;
446447
}
447448

448449
/* Advance the counts */
449-
((SetOpStatePerGroup)entry->additional)->numLeft++;
450+
pergroup->numLeft++;
450451

451452
/* Must reset expression context after each hashtable lookup */
452453
ResetExprContext(econtext);
@@ -478,7 +479,7 @@ setop_fill_hash_table(SetOpState *setopstate)
478479

479480
/* Advance the counts if entry is already present */
480481
if (entry)
481-
((SetOpStatePerGroup)entry->additional)->numRight++;
482+
((SetOpStatePerGroup)TupleHashEntryGetAdditional(entry))->numRight++;
482483

483484
/* Must reset expression context after each hashtable lookup */
484485
ResetExprContext(econtext);
@@ -496,7 +497,7 @@ setop_fill_hash_table(SetOpState *setopstate)
496497
staticTupleTableSlot*
497498
setop_retrieve_hash_table(SetOpState*setopstate)
498499
{
499-
TupleHashEntryData*entry;
500+
TupleHashEntryentry;
500501
TupleTableSlot*resultTupleSlot;
501502

502503
/*
@@ -526,12 +527,12 @@ setop_retrieve_hash_table(SetOpState *setopstate)
526527
* See if we should emit any copies of this tuple, and if so return
527528
* the first copy.
528529
*/
529-
set_output_count(setopstate, (SetOpStatePerGroup)entry->additional);
530+
set_output_count(setopstate, (SetOpStatePerGroup)TupleHashEntryGetAdditional(entry));
530531

531532
if (setopstate->numOutput>0)
532533
{
533534
setopstate->numOutput--;
534-
returnExecStoreMinimalTuple(entry->firstTuple,
535+
returnExecStoreMinimalTuple(TupleHashEntryGetTuple(entry),
535536
resultTupleSlot,
536537
false);
537538
}

‎src/backend/executor/nodeSubplan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot,
753753
{
754754
CHECK_FOR_INTERRUPTS();
755755

756-
ExecStoreMinimalTuple(entry->firstTuple,hashtable->tableslot, false);
756+
ExecStoreMinimalTuple(TupleHashEntryGetTuple(entry),hashtable->tableslot, false);
757757
if (!execTuplesUnequal(slot,hashtable->tableslot,
758758
numCols,keyColIdx,
759759
eqfunctions,

‎src/include/executor/executor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,12 @@ extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable,
148148
bool*isnew,uint32*hash);
149149
externuint32TupleHashTableHash(TupleHashTablehashtable,
150150
TupleTableSlot*slot);
151+
externsize_tTupleHashEntrySize(void);
151152
externTupleHashEntryLookupTupleHashEntryHash(TupleHashTablehashtable,
152153
TupleTableSlot*slot,
153154
bool*isnew,uint32hash);
155+
externMinimalTupleTupleHashEntryGetTuple(TupleHashEntryentry);
156+
externvoid*TupleHashEntryGetAdditional(TupleHashEntryentry);
154157
externTupleHashEntryFindTupleHashEntry(TupleHashTablehashtable,
155158
TupleTableSlot*slot,
156159
ExprState*eqcomp,

‎src/include/nodes/execnodes.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -806,17 +806,10 @@ typedef struct ExecAuxRowMark
806806
* point to tab_hash_expr and tab_eq_func respectively.
807807
* ----------------------------------------------------------------
808808
*/
809+
typedefstructTupleHashEntryDataTupleHashEntryData;
809810
typedefstructTupleHashEntryData*TupleHashEntry;
810811
typedefstructTupleHashTableData*TupleHashTable;
811812

812-
typedefstructTupleHashEntryData
813-
{
814-
MinimalTuplefirstTuple;/* copy of first tuple in this group */
815-
void*additional;/* user data */
816-
uint32status;/* hash status */
817-
uint32hash;/* hash value (cached) */
818-
}TupleHashEntryData;
819-
820813
/* define parameters necessary to generate the tuple hash table interface */
821814
#defineSH_PREFIX tuplehash
822815
#defineSH_ELEMENT_TYPE TupleHashEntryData
@@ -835,6 +828,7 @@ typedef struct TupleHashTableData
835828
Oid*tab_collations;/* collations for hash and comparison */
836829
MemoryContexttablecxt;/* memory context containing table */
837830
MemoryContexttempcxt;/* context for function evaluations */
831+
Sizeadditionalsize;/* size of additional data */
838832
TupleTableSlot*tableslot;/* slot for referencing table entries */
839833
/* The following fields are set transiently for each table search: */
840834
TupleTableSlot*inputslot;/* current input tuple's slot */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp