mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
Add support for building GiST index by sorting.
This adds a new optional support function to the GiST access method: sortsupport. If it is defined, the GiST index is built by sorting all data to the order defined by the sortsupport's comparator function, and packing the tuples in that order to GiST pages. This is similar to how B-tree index build works, and is much faster than inserting the tuples one by one. The resulting index is smaller too, because the pages are packed more tightly, upto 'fillfactor'. The normal build method works by splitting pages, which tends to lead to more wasted space. The quality of the resulting index depends on how good the opclass-defined sort order is. A good order preserves locality of the input data. As the first user of this facility, add 'sortsupport' function to the point_ops opclass. It sorts the points in Z-order (aka Morton Code), by interleaving the bits of the X and Y coordinates. Author: Andrey Borodin Reviewed-by: Pavel Borisov, Thomas Munro Discussion: https://www.postgresql.org/message-id/1A36620E-CAD8-4267-9067-FB31385E7C0D%40yandex-team.ru
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/gist.h"
|
||||
#include "access/nbtree.h"
|
||||
#include "catalog/pg_am.h"
|
||||
#include "fmgr.h"
|
||||
@@ -175,3 +176,36 @@ PrepareSortSupportFromIndexRel(Relation indexRel, int16 strategy,
|
||||
|
||||
FinishSortSupportFunction(opfamily, opcintype, ssup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in SortSupport given a GiST index relation
|
||||
*
|
||||
* Caller must previously have zeroed the SortSupportData structure and then
|
||||
* filled in ssup_cxt, ssup_attno, ssup_collation, and ssup_nulls_first. This
|
||||
* will fill in ssup_reverse (always false for GiST index build), as well as
|
||||
* the comparator function pointer.
|
||||
*/
|
||||
void
|
||||
PrepareSortSupportFromGistIndexRel(Relation indexRel, SortSupport ssup)
|
||||
{
|
||||
Oid opfamily = indexRel->rd_opfamily[ssup->ssup_attno - 1];
|
||||
Oid opcintype = indexRel->rd_opcintype[ssup->ssup_attno - 1];
|
||||
Oid sortSupportFunction;
|
||||
|
||||
Assert(ssup->comparator == NULL);
|
||||
|
||||
if (indexRel->rd_rel->relam != GIST_AM_OID)
|
||||
elog(ERROR, "unexpected non-gist AM: %u", indexRel->rd_rel->relam);
|
||||
ssup->ssup_reverse = false;
|
||||
|
||||
/*
|
||||
* Look up the sort support function. This is simpler than for B-tree
|
||||
* indexes because we don't support the old-style btree comparators.
|
||||
*/
|
||||
sortSupportFunction = get_opfamily_proc(opfamily, opcintype, opcintype,
|
||||
GIST_SORTSUPPORT_PROC);
|
||||
if (!OidIsValid(sortSupportFunction))
|
||||
elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
|
||||
GIST_SORTSUPPORT_PROC, opcintype, opcintype, opfamily);
|
||||
OidFunctionCall1(sortSupportFunction, PointerGetDatum(ssup));
|
||||
}
|
||||
|
||||
@@ -1167,6 +1167,63 @@ tuplesort_begin_index_hash(Relation heapRel,
|
||||
return state;
|
||||
}
|
||||
|
||||
Tuplesortstate *
|
||||
tuplesort_begin_index_gist(Relation heapRel,
|
||||
Relation indexRel,
|
||||
int workMem,
|
||||
SortCoordinate coordinate,
|
||||
bool randomAccess)
|
||||
{
|
||||
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
|
||||
randomAccess);
|
||||
MemoryContext oldcontext;
|
||||
int i;
|
||||
|
||||
oldcontext = MemoryContextSwitchTo(state->sortcontext);
|
||||
|
||||
#ifdef TRACE_SORT
|
||||
if (trace_sort)
|
||||
elog(LOG,
|
||||
"begin index sort: workMem = %d, randomAccess = %c",
|
||||
workMem, randomAccess ? 't' : 'f');
|
||||
#endif
|
||||
|
||||
state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
|
||||
|
||||
state->comparetup = comparetup_index_btree;
|
||||
state->copytup = copytup_index;
|
||||
state->writetup = writetup_index;
|
||||
state->readtup = readtup_index;
|
||||
|
||||
state->heapRel = heapRel;
|
||||
state->indexRel = indexRel;
|
||||
|
||||
/* Prepare SortSupport data for each column */
|
||||
state->sortKeys = (SortSupport) palloc0(state->nKeys *
|
||||
sizeof(SortSupportData));
|
||||
|
||||
for (i = 0; i < state->nKeys; i++)
|
||||
{
|
||||
SortSupport sortKey = state->sortKeys + i;
|
||||
|
||||
sortKey->ssup_cxt = CurrentMemoryContext;
|
||||
sortKey->ssup_collation = indexRel->rd_indcollation[i];
|
||||
sortKey->ssup_nulls_first = false;
|
||||
sortKey->ssup_attno = i + 1;
|
||||
/* Convey if abbreviation optimization is applicable in principle */
|
||||
sortKey->abbreviate = (i == 0);
|
||||
|
||||
AssertState(sortKey->ssup_attno != 0);
|
||||
|
||||
/* Look for a sort support function */
|
||||
PrepareSortSupportFromGistIndexRel(indexRel, sortKey);
|
||||
}
|
||||
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
Tuplesortstate *
|
||||
tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
|
||||
bool nullsFirstFlag, int workMem,
|
||||
|
||||
Reference in New Issue
Block a user