diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 571fb95532..8c4ca8c17e 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -312,6 +312,12 @@ struct Tuplesortstate */ bool haveDatum1; + /* + * When true, specialized sort comparators are able to skip calling the + * tiebreak function when sort keys compare equally. + */ + bool oneKeySort; + /* * This array holds the tuples now in sort memory. If we are in state * INITIAL, the tuples are in no particular order; if we are in state @@ -698,7 +704,7 @@ qsort_tuple_unsigned_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state) compare = ApplyUnsignedSortComparator(a->datum1, a->isnull1, b->datum1, b->isnull1, &state->sortKeys[0]); - if (compare != 0) + if (compare != 0 || state->oneKeySort) return compare; return state->comparetup(a, b, state); @@ -713,7 +719,7 @@ qsort_tuple_signed_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state) compare = ApplySignedSortComparator(a->datum1, a->isnull1, b->datum1, b->isnull1, &state->sortKeys[0]); - if (compare != 0) + if (compare != 0 || state->oneKeySort) return compare; return state->comparetup(a, b, state); @@ -728,7 +734,7 @@ qsort_tuple_int32_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state) compare = ApplyInt32SortComparator(a->datum1, a->isnull1, b->datum1, b->isnull1, &state->sortKeys[0]); - if (compare != 0) + if (compare != 0 || state->oneKeySort) return compare; return state->comparetup(a, b, state); @@ -959,6 +965,10 @@ tuplesort_begin_batch(Tuplesortstate *state) state->tapeset = NULL; + /* check if specialized sorts can skip calling the tiebreak function */ + state->oneKeySort = state->nKeys == 1 && + !state->sortKeys[0].abbrev_converter; + state->memtupcount = 0; /* @@ -1056,6 +1066,10 @@ tuplesort_begin_heap(TupleDesc tupDesc, PrepareSortSupportFromOrderingOp(sortOperators[i], sortKey); } + /* check if specialized sorts can skip calling the tiebreak function */ + state->oneKeySort = state->nKeys == 1 && + !state->sortKeys[0].abbrev_converter; + /* * The "onlyKey" optimization cannot be used with abbreviated keys, since * tie-breaker comparisons may be required. Typically, the optimization @@ -1167,6 +1181,10 @@ tuplesort_begin_cluster(TupleDesc tupDesc, PrepareSortSupportFromIndexRel(indexRel, strategy, sortKey); } + /* check if specialized sorts can skip calling the tiebreak function */ + state->oneKeySort = state->nKeys == 1 && + !state->sortKeys[0].abbrev_converter; + pfree(indexScanKey); MemoryContextSwitchTo(oldcontext); @@ -1248,6 +1266,12 @@ tuplesort_begin_index_btree(Relation heapRel, PrepareSortSupportFromIndexRel(indexRel, strategy, sortKey); } + /* + * Since we sort equal keys by ItemPointer, we can't skip the comparator + * call. + */ + state->oneKeySort = false; + pfree(indexScanKey); MemoryContextSwitchTo(oldcontext); @@ -1297,6 +1321,7 @@ tuplesort_begin_index_hash(Relation heapRel, state->high_mask = high_mask; state->low_mask = low_mask; state->max_buckets = max_buckets; + state->oneKeySort = false; MemoryContextSwitchTo(oldcontext); @@ -1356,6 +1381,10 @@ tuplesort_begin_index_gist(Relation heapRel, PrepareSortSupportFromGistIndexRel(indexRel, sortKey); } + /* check if specialized sorts can skip calling the tiebreak function */ + state->oneKeySort = state->nKeys == 1 && + !state->sortKeys[0].abbrev_converter; + MemoryContextSwitchTo(oldcontext); return state; @@ -1432,6 +1461,9 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, if (!state->sortKeys->abbrev_converter) state->onlyKey = state->sortKeys; + /* check if specialized sorts can skip calling the tiebreak function */ + state->oneKeySort = !state->sortKeys->abbrev_converter; + MemoryContextSwitchTo(oldcontext); return state;