Skip to content

Commit 9220362

Browse files
committed
Teach SP-GiST to do index-only scans.
Operator classes can specify whether or not they support this; this preserves the flexibility to use lossy representations within an index. In passing, move constant data about a given index into the rd_amcache cache area, instead of doing fresh lookups each time we start an index operation. This is mainly to try to make sure that spgcanreturn() has insignificant cost; I still don't have any proof that it matters for actual index accesses. Also, get rid of useless copying of FmgrInfo pointers; we can perfectly well use the relcache's versions in-place.
1 parent 3695a55 commit 9220362

File tree

10 files changed

+286
-172
lines changed

10 files changed

+286
-172
lines changed

doc/src/sgml/spgist.sgml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ typedef struct spgConfigOut
145145
{
146146
Oid prefixType; /* Data type of inner-tuple prefixes */
147147
Oid labelType; /* Data type of inner-tuple node labels */
148+
bool canReturnData; /* Opclass can reconstruct original data */
148149
bool longValuesOK; /* Opclass can cope with values > 1 page */
149150
} spgConfigOut;
150151
</programlisting>
@@ -159,6 +160,8 @@ typedef struct spgConfigOut
159160
<structfield>prefixType</> can be set to <literal>VOIDOID</>.
160161
Likewise, for operator classes that do not use node labels,
161162
<structfield>labelType</> can be set to <literal>VOIDOID</>.
163+
<structfield>canReturnData</> should be set true if the operator class
164+
is capable of reconstructing the originally-supplied index value.
162165
<structfield>longValuesOK</> should be set true only when the
163166
<structfield>attType</> is of variable length and the operator
164167
class is capable of segmenting long values by repeated suffixing
@@ -441,6 +444,7 @@ typedef struct spgInnerConsistentIn
441444

442445
Datum reconstructedValue; /* value reconstructed at parent */
443446
int level; /* current level (counting from zero) */
447+
bool returnData; /* original data must be returned? */
444448

445449
/* Data from current inner tuple */
446450
bool allTheSame; /* tuple is marked all-the-same? */
@@ -467,6 +471,9 @@ typedef struct spgInnerConsistentOut
467471
parent level.
468472
<structfield>level</> is the current inner tuple's level, starting at
469473
zero for the root level.
474+
<structfield>returnData</> is <literal>true</> if reconstructed data is
475+
required for this query; this will only be so if the
476+
<function>config</> function asserted <structfield>canReturnData</>.
470477
<structfield>allTheSame</> is true if the current inner tuple is
471478
marked <quote>all-the-same</>; in this case all the nodes have the
472479
same label (if any) and so either all or none of them match the query
@@ -525,12 +532,14 @@ typedef struct spgLeafConsistentIn
525532

526533
Datum reconstructedValue; /* value reconstructed at parent */
527534
int level; /* current level (counting from zero) */
535+
bool returnData; /* original data must be returned? */
528536

529537
Datum leafDatum; /* datum in leaf tuple */
530538
} spgLeafConsistentIn;
531539

532540
typedef struct spgLeafConsistentOut
533541
{
542+
Datum leafValue; /* reconstructed original data, if any */
534543
bool recheck; /* set true if operator must be rechecked */
535544
} spgLeafConsistentOut;
536545
</programlisting>
@@ -543,13 +552,19 @@ typedef struct spgLeafConsistentOut
543552
parent level.
544553
<structfield>level</> is the current leaf tuple's level, starting at
545554
zero for the root level.
555+
<structfield>returnData</> is <literal>true</> if reconstructed data is
556+
required for this query; this will only be so if the
557+
<function>config</> function asserted <structfield>canReturnData</>.
546558
<structfield>leafDatum</> is the key value stored in the current
547559
leaf tuple.
548560
</para>
549561

550562
<para>
551563
The function must return <literal>true</> if the leaf tuple matches the
552564
query, or <literal>false</> if not. In the <literal>true</> case,
565+
if <structfield>returnData</> is <literal>true</> then
566+
<structfield>leafValue</> must be set to the value originally supplied
567+
to be indexed for this leaf tuple. Also,
553568
<structfield>recheck</> may be set to <literal>true</> if the match
554569
is uncertain and so the operator must be re-applied to the actual heap
555570
tuple to verify the match.

src/backend/access/spgist/spgdoinsert.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "postgres.h"
1717

18+
#include "access/genam.h"
1819
#include "access/spgist_private.h"
1920
#include "miscadmin.h"
2021
#include "storage/bufmgr.h"
@@ -678,6 +679,7 @@ doPickSplit(Relation index, SpGistState *state,
678679
bool insertedNew = false;
679680
spgPickSplitIn in;
680681
spgPickSplitOut out;
682+
FmgrInfo *procinfo;
681683
bool includeNew;
682684
int i,
683685
max,
@@ -816,7 +818,8 @@ doPickSplit(Relation index, SpGistState *state,
816818
*/
817819
memset(&out, 0, sizeof(out));
818820

819-
FunctionCall2Coll(&state->picksplitFn,
821+
procinfo = index_getprocinfo(index, 1, SPGIST_PICKSPLIT_PROC);
822+
FunctionCall2Coll(procinfo,
820823
index->rd_indcollation[0],
821824
PointerGetDatum(&in),
822825
PointerGetDatum(&out));
@@ -1944,6 +1947,7 @@ spgdoinsert(Relation index, SpGistState *state,
19441947
SpGistInnerTuple innerTuple;
19451948
spgChooseIn in;
19461949
spgChooseOut out;
1950+
FmgrInfo *procinfo;
19471951

19481952
/*
19491953
* spgAddNode and spgSplitTuple cases will loop back to here to
@@ -1968,7 +1972,8 @@ spgdoinsert(Relation index, SpGistState *state,
19681972

19691973
memset(&out, 0, sizeof(out));
19701974

1971-
FunctionCall2Coll(&state->chooseFn,
1975+
procinfo = index_getprocinfo(index, 1, SPGIST_CHOOSE_PROC);
1976+
FunctionCall2Coll(procinfo,
19721977
index->rd_indcollation[0],
19731978
PointerGetDatum(&in),
19741979
PointerGetDatum(&out));

src/backend/access/spgist/spgkdtreeproc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ spg_kd_config(PG_FUNCTION_ARGS)
3030

3131
cfg->prefixType = FLOAT8OID;
3232
cfg->labelType = VOIDOID; /* we don't need node labels */
33+
cfg->canReturnData = true;
3334
cfg->longValuesOK = false;
3435
PG_RETURN_VOID();
3536
}

src/backend/access/spgist/spgquadtreeproc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ spg_quad_config(PG_FUNCTION_ARGS)
3030

3131
cfg->prefixType = POINTOID;
3232
cfg->labelType = VOIDOID; /* we don't need node labels */
33+
cfg->canReturnData = true;
3334
cfg->longValuesOK = false;
3435
PG_RETURN_VOID();
3536
}
@@ -324,6 +325,9 @@ spg_quad_leaf_consistent(PG_FUNCTION_ARGS)
324325
/* all tests are exact */
325326
out->recheck = false;
326327

328+
/* leafDatum is what it is... */
329+
out->leafValue = in->leafDatum;
330+
327331
switch (in->strategy)
328332
{
329333
case RTLeftStrategyNumber:

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy