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

Commit 5ea86e6

Browse files
committed
Use the sortsupport infrastructure in more cases.
This removes some fmgr overhead from cases such as btree index builds. Peter Geoghegan, reviewed by Andreas Karlsson and me.
1 parent 99e8f08 commit 5ea86e6

File tree

4 files changed

+206
-214
lines changed

4 files changed

+206
-214
lines changed

src/backend/access/nbtree/nbtsort.c

+33-30
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
686686
int i,
687687
keysz = RelationGetNumberOfAttributes(wstate->index);
688688
ScanKey indexScanKey = NULL;
689+
SortSupport sortKeys;
689690

690691
if (merge)
691692
{
@@ -701,6 +702,31 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
701702
true, &should_free2);
702703
indexScanKey = _bt_mkscankey_nodata(wstate->index);
703704

705+
/* Prepare SortSupport data for each column */
706+
sortKeys = (SortSupport) palloc0(keysz * sizeof(SortSupportData));
707+
708+
for (i = 0; i < keysz; i++)
709+
{
710+
SortSupport sortKey = sortKeys + i;
711+
ScanKey scanKey = indexScanKey + i;
712+
int16 strategy;
713+
714+
sortKey->ssup_cxt = CurrentMemoryContext;
715+
sortKey->ssup_collation = scanKey->sk_collation;
716+
sortKey->ssup_nulls_first =
717+
(scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0;
718+
sortKey->ssup_attno = scanKey->sk_attno;
719+
720+
AssertState(sortKey->ssup_attno != 0);
721+
722+
strategy = (scanKey->sk_flags & SK_BT_DESC) != 0 ?
723+
BTGreaterStrategyNumber : BTLessStrategyNumber;
724+
725+
PrepareSortSupportFromIndexRel(wstate->index, strategy, sortKey);
726+
}
727+
728+
_bt_freeskey(indexScanKey);
729+
704730
for (;;)
705731
{
706732
load1 = true; /* load BTSpool next ? */
@@ -713,43 +739,20 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
713739
{
714740
for (i = 1; i <= keysz; i++)
715741
{
716-
ScanKey entry;
742+
SortSupport entry;
717743
Datum attrDatum1,
718744
attrDatum2;
719745
bool isNull1,
720746
isNull2;
721747
int32 compare;
722748

723-
entry = indexScanKey + i - 1;
749+
entry = sortKeys + i - 1;
724750
attrDatum1 = index_getattr(itup, i, tupdes, &isNull1);
725751
attrDatum2 = index_getattr(itup2, i, tupdes, &isNull2);
726-
if (isNull1)
727-
{
728-
if (isNull2)
729-
compare = 0; /* NULL "=" NULL */
730-
else if (entry->sk_flags & SK_BT_NULLS_FIRST)
731-
compare = -1; /* NULL "<" NOT_NULL */
732-
else
733-
compare = 1; /* NULL ">" NOT_NULL */
734-
}
735-
else if (isNull2)
736-
{
737-
if (entry->sk_flags & SK_BT_NULLS_FIRST)
738-
compare = 1; /* NOT_NULL ">" NULL */
739-
else
740-
compare = -1; /* NOT_NULL "<" NULL */
741-
}
742-
else
743-
{
744-
compare =
745-
DatumGetInt32(FunctionCall2Coll(&entry->sk_func,
746-
entry->sk_collation,
747-
attrDatum1,
748-
attrDatum2));
749-
750-
if (entry->sk_flags & SK_BT_DESC)
751-
compare = -compare;
752-
}
752+
753+
compare = ApplySortComparator(attrDatum1, isNull1,
754+
attrDatum2, isNull2,
755+
entry);
753756
if (compare > 0)
754757
{
755758
load1 = false;
@@ -783,7 +786,7 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
783786
true, &should_free2);
784787
}
785788
}
786-
_bt_freeskey(indexScanKey);
789+
pfree(sortKeys);
787790
}
788791
else
789792
{

src/backend/utils/sort/sortsupport.c

+60-19
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "access/nbtree.h"
2222
#include "fmgr.h"
2323
#include "utils/lsyscache.h"
24+
#include "utils/rel.h"
2425
#include "utils/sortsupport.h"
2526

2627

@@ -86,28 +87,14 @@ PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup)
8687
}
8788

8889
/*
89-
* Fill in SortSupport given an ordering operator (btree "<" or ">" operator).
90-
*
91-
* Caller must previously have zeroed the SortSupportData structure and then
92-
* filled in ssup_cxt, ssup_collation, and ssup_nulls_first. This will fill
93-
* in ssup_reverse as well as the comparator function pointer.
90+
* Look up and call sortsupport function to setup SortSupport comparator;
91+
* or if no such function exists or it declines to set up the appropriate
92+
* state, prepare a suitable shim.
9493
*/
95-
void
96-
PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
94+
static void
95+
FinishSortSupportFunction(Oid opfamily, Oid opcintype, SortSupport ssup)
9796
{
9897
Oid sortSupportFunction;
99-
Oid opfamily;
100-
Oid opcintype;
101-
int16 strategy;
102-
103-
Assert(ssup->comparator == NULL);
104-
105-
/* Find the operator in pg_amop */
106-
if (!get_ordering_op_properties(orderingOp, &opfamily, &opcintype,
107-
&strategy))
108-
elog(ERROR, "operator %u is not a valid ordering operator",
109-
orderingOp);
110-
ssup->ssup_reverse = (strategy == BTGreaterStrategyNumber);
11198

11299
/* Look for a sort support function */
113100
sortSupportFunction = get_opfamily_proc(opfamily, opcintype, opcintype,
@@ -136,3 +123,57 @@ PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
136123
PrepareSortSupportComparisonShim(sortFunction, ssup);
137124
}
138125
}
126+
127+
/*
128+
* Fill in SortSupport given an ordering operator (btree "<" or ">" operator).
129+
*
130+
* Caller must previously have zeroed the SortSupportData structure and then
131+
* filled in ssup_cxt, ssup_collation, and ssup_nulls_first. This will fill
132+
* in ssup_reverse as well as the comparator function pointer.
133+
*/
134+
void
135+
PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
136+
{
137+
Oid opfamily;
138+
Oid opcintype;
139+
int16 strategy;
140+
141+
Assert(ssup->comparator == NULL);
142+
143+
/* Find the operator in pg_amop */
144+
if (!get_ordering_op_properties(orderingOp, &opfamily, &opcintype,
145+
&strategy))
146+
elog(ERROR, "operator %u is not a valid ordering operator",
147+
orderingOp);
148+
ssup->ssup_reverse = (strategy == BTGreaterStrategyNumber);
149+
150+
FinishSortSupportFunction(opfamily, opcintype, ssup);
151+
}
152+
153+
/*
154+
* Fill in SortSupport given an index relation, attribute, and strategy.
155+
*
156+
* Caller must previously have zeroed the SortSupportData structure and then
157+
* filled in ssup_cxt, ssup_attno, ssup_collation, and ssup_nulls_first. This
158+
* will fill in ssup_reverse (based on the supplied strategy), as well as the
159+
* comparator function pointer.
160+
*/
161+
void
162+
PrepareSortSupportFromIndexRel(Relation indexRel, int16 strategy,
163+
SortSupport ssup)
164+
{
165+
Oid opfamily = indexRel->rd_opfamily[ssup->ssup_attno - 1];
166+
Oid opcintype = indexRel->rd_opcintype[ssup->ssup_attno - 1];
167+
168+
Assert(ssup->comparator == NULL);
169+
170+
/* Find the operator in pg_amop */
171+
if (indexRel->rd_rel->relam != BTREE_AM_OID)
172+
elog(ERROR, "unexpected non-btree AM: %u", indexRel->rd_rel->relam);
173+
if (strategy != BTGreaterStrategyNumber &&
174+
strategy != BTLessStrategyNumber)
175+
elog(ERROR, "unexpected sort support strategy: %d", strategy);
176+
ssup->ssup_reverse = (strategy == BTGreaterStrategyNumber);
177+
178+
FinishSortSupportFunction(opfamily, opcintype, ssup);
179+
}

0 commit comments

Comments
 (0)