Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 78efd5c

Browse files
committed
Extend abbreviated key infrastructure to datum tuplesorts.
Andrew Gierth, reviewed by Peter Geoghegan and by me.
1 parent 0bb8528 commit 78efd5c

File tree

3 files changed

+101
-41
lines changed

3 files changed

+101
-41
lines changed

src/backend/executor/nodeAgg.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -363,10 +363,6 @@ initialize_aggregates(AggState *aggstate,
363363
* We use a plain Datum sorter when there's a single input column;
364364
* otherwise sort the full tuple. (See comments for
365365
* process_ordered_aggregate_single.)
366-
*
367-
* In the future, we should consider forcing the
368-
* tuplesort_begin_heap() case when the abbreviated key
369-
* optimization can thereby be used, even when numInputs is 1.
370366
*/
371367
peraggstate->sortstate =
372368
(peraggstate->numInputs == 1) ?

src/backend/utils/adt/orderedsetaggs.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,6 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
268268

269269
/*
270270
* Initialize tuplesort object.
271-
*
272-
* In the future, we should consider forcing the tuplesort_begin_heap()
273-
* case when the abbreviated key optimization can thereby be used, even
274-
* when !use_tuples.
275271
*/
276272
if (use_tuples)
277273
osastate->sortstate = tuplesort_begin_heap(qstate->tupdesc,

src/backend/utils/sort/tuplesort.c

Lines changed: 101 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,18 @@ bool optimize_bounded_sort = true;
147147
* case where the first key determines the comparison result. Note that
148148
* for a pass-by-reference datatype, datum1 points into the "tuple" storage.
149149
*
150+
* There is one special case: when the sort support infrastructure provides an
151+
* "abbreviated key" representation, where the key is (typically) a pass by
152+
* value proxy for a pass by reference type. In this case, the abbreviated key
153+
* is stored in datum1 in place of the actual first key column.
154+
*
150155
* When sorting single Datums, the data value is represented directly by
151-
* datum1/isnull1. If the datatype is pass-by-reference and isnull1 is false,
152-
* then datum1 points to a separately palloc'd data value that is also pointed
153-
* to by the "tuple" pointer; otherwise "tuple" is NULL. There is one special
154-
* case: when the sort support infrastructure provides an "abbreviated key"
155-
* representation, where the key is (typically) a pass by value proxy for a
156-
* pass by reference type.
156+
* datum1/isnull1 for pass by value types (or null values). If the datatype is
157+
* pass-by-reference and isnull1 is false, then "tuple" points to a separately
158+
* palloc'd data value, otherwise "tuple" is NULL. The value of datum1 is then
159+
* either the same pointer as "tuple", or is an abbreviated key value as
160+
* described above. Accordingly, "tuple" is always used in preference to
161+
* datum1 as the authoritative value for pass-by-reference cases.
157162
*
158163
* While building initial runs, tupindex holds the tuple's run number. During
159164
* merge passes, we re-use it to hold the input tape number that each tuple in
@@ -901,30 +906,36 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
901906
state->copytup = copytup_datum;
902907
state->writetup = writetup_datum;
903908
state->readtup = readtup_datum;
909+
state->abbrevNext = 10;
904910

905911
state->datumType = datumType;
906912

907-
/* Prepare SortSupport data */
908-
state->onlyKey = (SortSupport) palloc0(sizeof(SortSupportData));
909-
910-
state->onlyKey->ssup_cxt = CurrentMemoryContext;
911-
state->onlyKey->ssup_collation = sortCollation;
912-
state->onlyKey->ssup_nulls_first = nullsFirstFlag;
913-
/*
914-
* Conversion to abbreviated representation infeasible in the Datum case.
915-
* It must be possible to subsequently fetch original datum values within
916-
* tuplesort_getdatum(), which would require special-case preservation of
917-
* original values.
918-
*/
919-
state->onlyKey->abbreviate = false;
920-
921-
PrepareSortSupportFromOrderingOp(sortOperator, state->onlyKey);
922-
923913
/* lookup necessary attributes of the datum type */
924914
get_typlenbyval(datumType, &typlen, &typbyval);
925915
state->datumTypeLen = typlen;
926916
state->datumTypeByVal = typbyval;
927917

918+
/* Prepare SortSupport data */
919+
state->sortKeys = (SortSupport) palloc0(sizeof(SortSupportData));
920+
921+
state->sortKeys->ssup_cxt = CurrentMemoryContext;
922+
state->sortKeys->ssup_collation = sortCollation;
923+
state->sortKeys->ssup_nulls_first = nullsFirstFlag;
924+
925+
/* abbreviation is possible here only for by-reference types */
926+
state->sortKeys->abbreviate = !typbyval;
927+
928+
PrepareSortSupportFromOrderingOp(sortOperator, state->sortKeys);
929+
930+
/*
931+
* The "onlyKey" optimization cannot be used with abbreviated keys, since
932+
* tie-breaker comparisons may be required. Typically, the optimization is
933+
* only of value to pass-by-value types anyway, whereas abbreviated keys
934+
* are typically only of value to pass-by-reference types.
935+
*/
936+
if (!state->sortKeys->abbrev_converter)
937+
state->onlyKey = state->sortKeys;
938+
928939
MemoryContextSwitchTo(oldcontext);
929940

930941
return state;
@@ -1307,9 +1318,17 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
13071318
SortTuple stup;
13081319

13091320
/*
1310-
* If it's a pass-by-reference value, copy it into memory we control, and
1311-
* decrease availMem. Then call the common code.
1321+
* Pass-by-value types or null values are just stored directly in
1322+
* stup.datum1 (and stup.tuple is not used and set to NULL).
1323+
*
1324+
* Non-null pass-by-reference values need to be copied into memory we
1325+
* control, and possibly abbreviated. The copied value is pointed to by
1326+
* stup.tuple and is treated as the canonical copy (e.g. to return via
1327+
* tuplesort_getdatum or when writing to tape); stup.datum1 gets the
1328+
* abbreviated value if abbreviation is happening, otherwise it's identical
1329+
* to stup.tuple.
13121330
*/
1331+
13131332
if (isNull || state->datumTypeByVal)
13141333
{
13151334
stup.datum1 = val;
@@ -1318,10 +1337,44 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
13181337
}
13191338
else
13201339
{
1321-
stup.datum1 = datumCopy(val, false, state->datumTypeLen);
1340+
Datum original = datumCopy(val, false, state->datumTypeLen);
1341+
13221342
stup.isnull1 = false;
1323-
stup.tuple = DatumGetPointer(stup.datum1);
1343+
stup.tuple = DatumGetPointer(original);
13241344
USEMEM(state, GetMemoryChunkSpace(stup.tuple));
1345+
1346+
if (!state->sortKeys->abbrev_converter)
1347+
{
1348+
stup.datum1 = original;
1349+
}
1350+
else if (!consider_abort_common(state))
1351+
{
1352+
/* Store abbreviated key representation */
1353+
stup.datum1 = state->sortKeys->abbrev_converter(original,
1354+
state->sortKeys);
1355+
}
1356+
else
1357+
{
1358+
/* Abort abbreviation */
1359+
int i;
1360+
1361+
stup.datum1 = original;
1362+
1363+
/*
1364+
* Set state to be consistent with never trying abbreviation.
1365+
*
1366+
* Alter datum1 representation in already-copied tuples, so as to
1367+
* ensure a consistent representation (current tuple was just handled).
1368+
* Note that we rely on all tuples copied so far actually being
1369+
* contained within memtuples array.
1370+
*/
1371+
for (i = 0; i < state->memtupcount; i++)
1372+
{
1373+
SortTuple *mtup = &state->memtuples[i];
1374+
1375+
mtup->datum1 = PointerGetDatum(mtup->tuple);
1376+
}
1377+
}
13251378
}
13261379

13271380
puttuple_common(state, &stup);
@@ -1886,10 +1939,12 @@ tuplesort_getdatum(Tuplesortstate *state, bool forward,
18861939
}
18871940
else
18881941
{
1942+
/* use stup.tuple because stup.datum1 may be an abbreviation */
1943+
18891944
if (should_free)
1890-
*val = stup.datum1;
1945+
*val = PointerGetDatum(stup.tuple);
18911946
else
1892-
*val = datumCopy(stup.datum1, false, state->datumTypeLen);
1947+
*val = datumCopy(PointerGetDatum(stup.tuple), false, state->datumTypeLen);
18931948
*isNull = false;
18941949
}
18951950

@@ -3715,9 +3770,22 @@ readtup_index(Tuplesortstate *state, SortTuple *stup,
37153770
static int
37163771
comparetup_datum(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
37173772
{
3718-
return ApplySortComparator(a->datum1, a->isnull1,
3719-
b->datum1, b->isnull1,
3720-
state->onlyKey);
3773+
int compare;
3774+
3775+
compare = ApplySortComparator(a->datum1, a->isnull1,
3776+
b->datum1, b->isnull1,
3777+
state->sortKeys);
3778+
if (compare != 0)
3779+
return compare;
3780+
3781+
/* if we have abbreviations, then "tuple" has the original value */
3782+
3783+
if (state->sortKeys->abbrev_converter)
3784+
compare = ApplySortAbbrevFullComparator(PointerGetDatum(a->tuple), a->isnull1,
3785+
PointerGetDatum(b->tuple), b->isnull1,
3786+
state->sortKeys);
3787+
3788+
return compare;
37213789
}
37223790

37233791
static void
@@ -3746,8 +3814,8 @@ writetup_datum(Tuplesortstate *state, int tapenum, SortTuple *stup)
37463814
}
37473815
else
37483816
{
3749-
waddr = DatumGetPointer(stup->datum1);
3750-
tuplen = datumGetSize(stup->datum1, false, state->datumTypeLen);
3817+
waddr = stup->tuple;
3818+
tuplen = datumGetSize(PointerGetDatum(stup->tuple), false, state->datumTypeLen);
37513819
Assert(tuplen != 0);
37523820
}
37533821

0 commit comments

Comments
 (0)