Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd583f10

Browse files
committed
Create core infrastructure for KNNGIST.
This is a heavily revised version of builtin_knngist_core-0.9. Theordering operators are no longer mixed in with actual quals, which wouldhave confused not only humans but significant parts of the planner.Instead, ordering operators are carried separately throughout planning andexecution.Since the API for ambeginscan and amrescan functions had to be changedanyway, this commit takes the opportunity to rationalize that a bit.RelationGetIndexScan no longer forces a premature index_rescan call;instead, callers of index_beginscan must call index_rescan too. Aside frommaking the AM-side initialization logic a bit less peculiar, this has theadvantage that we do not make a useless extra am_rescan call when there areruntime key values. AMs formerly could not assume that the key valuespassed to amrescan were actually valid; now they can.Teodor Sigaev and Tom Lane
1 parentd7e5d15 commitd583f10

40 files changed

+790
-314
lines changed

‎doc/src/sgml/catalogs.sgml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@
510510
<entry><structfield>ambeginscan</structfield></entry>
511511
<entry><type>regproc</type></entry>
512512
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
513-
<entry><quote>Start new scan</quote> function</entry>
513+
<entry><quote>Prepare for index scan</quote> function</entry>
514514
</row>
515515

516516
<row>
@@ -531,14 +531,14 @@
531531
<entry><structfield>amrescan</structfield></entry>
532532
<entry><type>regproc</type></entry>
533533
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
534-
<entry><quote>Restart this scan</quote> function</entry>
534+
<entry><quote>(Re)start index scan</quote> function</entry>
535535
</row>
536536

537537
<row>
538538
<entry><structfield>amendscan</structfield></entry>
539539
<entry><type>regproc</type></entry>
540540
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
541-
<entry><quote>End this scan</quote> function</entry>
541+
<entry><quote>Clean up after index scan</quote> function</entry>
542542
</row>
543543

544544
<row>

‎doc/src/sgml/indexam.sgml

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ void
268268
amcostestimate (PlannerInfo *root,
269269
IndexOptInfo *index,
270270
List *indexQuals,
271+
List *indexOrderBys,
271272
RelOptInfo *outer_rel,
272273
Cost *indexStartupCost,
273274
Cost *indexTotalCost,
@@ -318,19 +319,42 @@ amoptions (ArrayType *reloptions,
318319
IndexScanDesc
319320
ambeginscan (Relation indexRelation,
320321
int nkeys,
321-
ScanKey key);
322+
int norderbys);
322323
</programlisting>
323-
Begin a new scan. The <literal>key</> array (of length <literal>nkeys</>)
324-
describes the scan key(s) for the index scan. The result must be a
325-
palloc'd struct. For implementation reasons the index access method
324+
Prepare for an index scan. The <literal>nkeys</> and <literal>norderbys</>
325+
parameters indicate the number of quals and ordering operators that will be
326+
used in the scan; these may be useful for space allocation purposes.
327+
Note that the actual values of the scan keys aren't provided yet.
328+
The result must be a palloc'd struct.
329+
For implementation reasons the index access method
326330
<emphasis>must</> create this struct by calling
327331
<function>RelationGetIndexScan()</>. In most cases
328-
<function>ambeginscan</> itself does little beyond making that call;
332+
<function>ambeginscan</> does little beyond making that call and perhaps
333+
acquiring locks;
329334
the interesting parts of index-scan startup are in <function>amrescan</>.
330335
</para>
331336

332337
<para>
333338
<programlisting>
339+
void
340+
amrescan (IndexScanDesc scan,
341+
ScanKey keys,
342+
int nkeys,
343+
ScanKey orderbys,
344+
int norderbys);
345+
</programlisting>
346+
Start or restart an indexscan, possibly with new scan keys. (To restart
347+
using previously-passed keys, NULL is passed for <literal>keys</> and/or
348+
<literal>orderbys</>.) Note that it is not allowed for
349+
the number of keys or order-by operators to be larger than
350+
what was passed to <function>ambeginscan</>. In practice the restart
351+
feature is used when a new outer tuple is selected by a nested-loop join
352+
and so a new key comparison value is needed, but the scan key structure
353+
remains the same.
354+
</para>
355+
356+
<para>
357+
<programlisting>
334358
boolean
335359
amgettuple (IndexScanDesc scan,
336360
ScanDirection direction);
@@ -393,22 +417,6 @@ amgetbitmap (IndexScanDesc scan,
393417
<para>
394418
<programlisting>
395419
void
396-
amrescan (IndexScanDesc scan,
397-
ScanKey key);
398-
</programlisting>
399-
Restart the given scan, possibly with new scan keys (to continue using
400-
the old keys, NULL is passed for <literal>key</>). Note that it is not
401-
possible for the number of keys to be changed. In practice the restart
402-
feature is used when a new outer tuple is selected by a nested-loop join
403-
and so a new key comparison value is needed, but the scan key structure
404-
remains the same. This function is also called by
405-
<function>RelationGetIndexScan()</>, so it is used for initial setup
406-
of an index scan as well as rescanning.
407-
</para>
408-
409-
<para>
410-
<programlisting>
411-
void
412420
amendscan (IndexScanDesc scan);
413421
</programlisting>
414422
End a scan and release resources. The <literal>scan</> struct itself
@@ -820,8 +828,9 @@ amrestrpos (IndexScanDesc scan);
820828
<title>Index Cost Estimation Functions</title>
821829

822830
<para>
823-
The <function>amcostestimate</> function is given a list of WHERE clauses that have
824-
been determined to be usable with the index. It must return estimates
831+
The <function>amcostestimate</> function is given information describing
832+
a possible index scan, including lists of WHERE and ORDER BY clauses that
833+
have been determined to be usable with the index. It must return estimates
825834
of the cost of accessing the index and the selectivity of the WHERE
826835
clauses (that is, the fraction of parent-table rows that will be
827836
retrieved during the index scan). For simple cases, nearly all the
@@ -839,14 +848,15 @@ void
839848
amcostestimate (PlannerInfo *root,
840849
IndexOptInfo *index,
841850
List *indexQuals,
851+
List *indexOrderBys,
842852
RelOptInfo *outer_rel,
843853
Cost *indexStartupCost,
844854
Cost *indexTotalCost,
845855
Selectivity *indexSelectivity,
846856
double *indexCorrelation);
847857
</programlisting>
848858

849-
The firstfour parameters are inputs:
859+
The firstfive parameters are inputs:
850860

851861
<variablelist>
852862
<varlistentry>
@@ -873,6 +883,17 @@ amcostestimate (PlannerInfo *root,
873883
<para>
874884
List of index qual clauses (implicitly ANDed);
875885
a <symbol>NIL</> list indicates no qualifiers are available.
886+
Note that the list contains expression trees with RestrictInfo nodes
887+
at the top, not ScanKeys.
888+
</para>
889+
</listitem>
890+
</varlistentry>
891+
892+
<varlistentry>
893+
<term><parameter>indexOrderBys</></term>
894+
<listitem>
895+
<para>
896+
List of indexable ORDER BY operators, or <symbol>NIL</> if none.
876897
Note that the list contains expression trees, not ScanKeys.
877898
</para>
878899
</listitem>

‎src/backend/access/gin/ginscan.c

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,28 @@ Datum
2626
ginbeginscan(PG_FUNCTION_ARGS)
2727
{
2828
Relationrel= (Relation)PG_GETARG_POINTER(0);
29-
intkeysz=PG_GETARG_INT32(1);
30-
ScanKeyscankey=(ScanKey)PG_GETARG_POINTER(2);
29+
intnkeys=PG_GETARG_INT32(1);
30+
intnorderbys=PG_GETARG_INT32(2);
3131
IndexScanDescscan;
32+
GinScanOpaqueso;
33+
34+
/* no order by operators allowed */
35+
Assert(norderbys==0);
36+
37+
scan=RelationGetIndexScan(rel,nkeys,norderbys);
38+
39+
/* allocate private workspace */
40+
so= (GinScanOpaque)palloc(sizeof(GinScanOpaqueData));
41+
so->keys=NULL;
42+
so->nkeys=0;
43+
so->tempCtx=AllocSetContextCreate(CurrentMemoryContext,
44+
"Gin scan temporary context",
45+
ALLOCSET_DEFAULT_MINSIZE,
46+
ALLOCSET_DEFAULT_INITSIZE,
47+
ALLOCSET_DEFAULT_MAXSIZE);
48+
initGinState(&so->ginstate,scan->indexRelation);
3249

33-
scan=RelationGetIndexScan(rel,keysz,scankey);
50+
scan->opaque=so;
3451

3552
PG_RETURN_POINTER(scan);
3653
}
@@ -241,27 +258,10 @@ ginrescan(PG_FUNCTION_ARGS)
241258
{
242259
IndexScanDescscan= (IndexScanDesc)PG_GETARG_POINTER(0);
243260
ScanKeyscankey= (ScanKey)PG_GETARG_POINTER(1);
244-
GinScanOpaqueso;
245-
246-
so= (GinScanOpaque)scan->opaque;
247-
248-
if (so==NULL)
249-
{
250-
/* if called from ginbeginscan */
251-
so= (GinScanOpaque)palloc(sizeof(GinScanOpaqueData));
252-
so->tempCtx=AllocSetContextCreate(CurrentMemoryContext,
253-
"Gin scan temporary context",
254-
ALLOCSET_DEFAULT_MINSIZE,
255-
ALLOCSET_DEFAULT_INITSIZE,
256-
ALLOCSET_DEFAULT_MAXSIZE);
257-
initGinState(&so->ginstate,scan->indexRelation);
258-
scan->opaque=so;
259-
}
260-
else
261-
{
262-
freeScanKeys(so->keys,so->nkeys);
263-
}
261+
/* remaining arguments are ignored */
262+
GinScanOpaqueso= (GinScanOpaque)scan->opaque;
264263

264+
freeScanKeys(so->keys,so->nkeys);
265265
so->keys=NULL;
266266

267267
if (scankey&&scan->numberOfKeys>0)
@@ -280,14 +280,11 @@ ginendscan(PG_FUNCTION_ARGS)
280280
IndexScanDescscan= (IndexScanDesc)PG_GETARG_POINTER(0);
281281
GinScanOpaqueso= (GinScanOpaque)scan->opaque;
282282

283-
if (so!=NULL)
284-
{
285-
freeScanKeys(so->keys,so->nkeys);
283+
freeScanKeys(so->keys,so->nkeys);
286284

287-
MemoryContextDelete(so->tempCtx);
285+
MemoryContextDelete(so->tempCtx);
288286

289-
pfree(so);
290-
}
287+
pfree(so);
291288

292289
PG_RETURN_VOID();
293290
}

‎src/backend/access/gist/gistscan.c

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,24 @@ gistbeginscan(PG_FUNCTION_ARGS)
2828
{
2929
Relationr= (Relation)PG_GETARG_POINTER(0);
3030
intnkeys=PG_GETARG_INT32(1);
31-
ScanKeykey=(ScanKey)PG_GETARG_POINTER(2);
31+
intnorderbys=PG_GETARG_INT32(2);
3232
IndexScanDescscan;
33+
GISTScanOpaqueso;
34+
35+
/* no order by operators allowed */
36+
Assert(norderbys==0);
37+
38+
scan=RelationGetIndexScan(r,nkeys,norderbys);
39+
40+
/* initialize opaque data */
41+
so= (GISTScanOpaque)palloc(sizeof(GISTScanOpaqueData));
42+
so->stack=NULL;
43+
so->tempCxt=createTempGistContext();
44+
so->curbuf=InvalidBuffer;
45+
so->giststate= (GISTSTATE*)palloc(sizeof(GISTSTATE));
46+
initGISTstate(so->giststate,scan->indexRelation);
3347

34-
scan=RelationGetIndexScan(r,nkeys,key);
48+
scan->opaque=so;
3549

3650
PG_RETURN_POINTER(scan);
3751
}
@@ -41,33 +55,18 @@ gistrescan(PG_FUNCTION_ARGS)
4155
{
4256
IndexScanDescscan= (IndexScanDesc)PG_GETARG_POINTER(0);
4357
ScanKeykey= (ScanKey)PG_GETARG_POINTER(1);
44-
GISTScanOpaqueso;
58+
/* remaining arguments are ignored */
59+
GISTScanOpaqueso= (GISTScanOpaque)scan->opaque;
4560
inti;
4661

47-
so= (GISTScanOpaque)scan->opaque;
48-
if (so!=NULL)
62+
/* rescan an existing indexscan --- reset state */
63+
gistfreestack(so->stack);
64+
so->stack=NULL;
65+
/* drop pins on buffers -- no locks held */
66+
if (BufferIsValid(so->curbuf))
4967
{
50-
/* rescan an existing indexscan --- reset state */
51-
gistfreestack(so->stack);
52-
so->stack=NULL;
53-
/* drop pins on buffers -- no locks held */
54-
if (BufferIsValid(so->curbuf))
55-
{
56-
ReleaseBuffer(so->curbuf);
57-
so->curbuf=InvalidBuffer;
58-
}
59-
}
60-
else
61-
{
62-
/* initialize opaque data */
63-
so= (GISTScanOpaque)palloc(sizeof(GISTScanOpaqueData));
64-
so->stack=NULL;
65-
so->tempCxt=createTempGistContext();
68+
ReleaseBuffer(so->curbuf);
6669
so->curbuf=InvalidBuffer;
67-
so->giststate= (GISTSTATE*)palloc(sizeof(GISTSTATE));
68-
initGISTstate(so->giststate,scan->indexRelation);
69-
70-
scan->opaque=so;
7170
}
7271

7372
/*
@@ -130,21 +129,16 @@ Datum
130129
gistendscan(PG_FUNCTION_ARGS)
131130
{
132131
IndexScanDescscan= (IndexScanDesc)PG_GETARG_POINTER(0);
133-
GISTScanOpaqueso;
134-
135-
so= (GISTScanOpaque)scan->opaque;
136-
137-
if (so!=NULL)
138-
{
139-
gistfreestack(so->stack);
140-
if (so->giststate!=NULL)
141-
freeGISTstate(so->giststate);
142-
/* drop pins on buffers -- we aren't holding any locks */
143-
if (BufferIsValid(so->curbuf))
144-
ReleaseBuffer(so->curbuf);
145-
MemoryContextDelete(so->tempCxt);
146-
pfree(scan->opaque);
147-
}
132+
GISTScanOpaqueso= (GISTScanOpaque)scan->opaque;
133+
134+
gistfreestack(so->stack);
135+
if (so->giststate!=NULL)
136+
freeGISTstate(so->giststate);
137+
/* drop pins on buffers -- we aren't holding any locks */
138+
if (BufferIsValid(so->curbuf))
139+
ReleaseBuffer(so->curbuf);
140+
MemoryContextDelete(so->tempCxt);
141+
pfree(so);
148142

149143
PG_RETURN_VOID();
150144
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp