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

Commite573459

Browse files
committed
Clean up API for ambulkdelete/amvacuumcleanup as per today's discussion.
This formulation requires every AM to provide amvacuumcleanup, unlike before,but it's surely a whole lot cleaner. Also, add an 'amstorage' column topg_am so that we can get rid of hardwired knowledge in DefineOpClass().
1 parentd3171dd commite573459

File tree

16 files changed

+308
-373
lines changed

16 files changed

+308
-373
lines changed

‎doc/src/sgml/catalogs.sgml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.121 2006/03/10 19:10:46 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.122 2006/05/02 22:25:09 tgl Exp $ -->
22
<!--
33
Documentation of the system catalogs, directed toward PostgreSQL developers
44
-->
@@ -394,13 +394,27 @@
394394
<entry>Does the access method support null index entries?</entry>
395395
</row>
396396

397+
<row>
398+
<entry><structfield>amstorage</structfield></entry>
399+
<entry><type>bool</type></entry>
400+
<entry></entry>
401+
<entry>Can index storage data type differ from column data type?</entry>
402+
</row>
403+
397404
<row>
398405
<entry><structfield>amconcurrent</structfield></entry>
399406
<entry><type>bool</type></entry>
400407
<entry></entry>
401408
<entry>Does the access method support concurrent updates?</entry>
402409
</row>
403410

411+
<row>
412+
<entry><structfield>amclusterable</structfield></entry>
413+
<entry><type>bool</type></entry>
414+
<entry></entry>
415+
<entry>Can an index of this type be CLUSTERed on?</entry>
416+
</row>
417+
404418
<row>
405419
<entry><structfield>aminsert</structfield></entry>
406420
<entry><type>regproc</type></entry>

‎doc/src/sgml/indexam.sgml

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.9 2006/03/10 19:10:48 momjian Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.10 2006/05/02 22:25:09 tgl Exp $ -->
22

33
<chapter id="indexam">
44
<title>Index Access Method Interface Definition</title>
@@ -184,44 +184,52 @@ aminsert (Relation indexRelation,
184184
<para>
185185
<programlisting>
186186
IndexBulkDeleteResult *
187-
ambulkdelete (Relation indexRelation,
187+
ambulkdelete (IndexVacuumInfo *info,
188+
IndexBulkDeleteResult *stats,
188189
IndexBulkDeleteCallback callback,
189190
void *callback_state);
190191
</programlisting>
191192
Delete tuple(s) from the index. This is a <quote>bulk delete</> operation
192193
that is intended to be implemented by scanning the whole index and checking
193194
each entry to see if it should be deleted.
194-
The passed-in <literal>callback</> functionmay be called, in the style
195+
The passed-in <literal>callback</> functionmust be called, in the style
195196
<literal>callback(<replaceable>TID</>, callback_state) returns bool</literal>,
196197
to determine whether any particular index entry, as identified by its
197198
referenced TID, is to be deleted. Must return either NULL or a palloc'd
198199
struct containing statistics about the effects of the deletion operation.
200+
It is OK to return NULL if no information needs to be passed on to
201+
<function>amvacuumcleanup</>.
199202
</para>
200203

201204
<para>
202-
If <literal>callback_state</> is NULL then no tuples are to be deleted.
203-
The index AM may choose to optimize this case (eg by not scanning the
204-
index) but it is still expected to deliver accurate statistics.
205+
Because of limited <varname>maintenance_work_mem</>,
206+
<function>ambulkdelete</> may need to be called more than once when many
207+
tuples are to be deleted. The <literal>stats</> argument is the result
208+
of the previous call for this index (it is NULL for the first call within a
209+
<command>VACUUM</> operation). This allows the AM to accumulate statistics
210+
across the whole operation. Typically, <function>ambulkdelete</> will
211+
modify and return the same struct if the passed <literal>stats</> is not
212+
null.
205213
</para>
206214

207215
<para>
208216
<programlisting>
209217
IndexBulkDeleteResult *
210-
amvacuumcleanup (Relation indexRelation,
211-
IndexVacuumCleanupInfo *info,
218+
amvacuumcleanup (IndexVacuumInfo *info,
212219
IndexBulkDeleteResult *stats);
213220
</programlisting>
214-
Clean up after a <command>VACUUM</command> operation (one or more
215-
<function>ambulkdelete</> calls). An index access method does not have
216-
to provide this function (if so, the entry in <structname>pg_am</> must
217-
be zero). If it is provided, it is typically used for bulk cleanup
218-
such as reclaiming empty index pages. <literal>info</>
219-
provides some additional arguments such as a message level for statistical
220-
reports, and <literal>stats</> is whatever the last
221-
<function>ambulkdelete</> call returned. <function>amvacuumcleanup</>
222-
may replace or modify this struct before returning it. If the result
223-
is not NULL it must be a palloc'd struct. The statistics it contains
224-
will be reported by <command>VACUUM</> if <literal>VERBOSE</> is given.
221+
Clean up after a <command>VACUUM</command> operation (zero or more
222+
<function>ambulkdelete</> calls). This does not have to do anything
223+
beyond returning index statistics, but it may perform bulk cleanup
224+
such as reclaiming empty index pages. <literal>stats</> is whatever the
225+
last <function>ambulkdelete</> call returned, or NULL if
226+
<function>ambulkdelete</> was not called because no tuples needed to be
227+
deleted. If the result is not NULL it must be a palloc'd struct.
228+
The statistics it contains will be used to update <structname>pg_class</>,
229+
and will be reported by <command>VACUUM</> if <literal>VERBOSE</> is given.
230+
It is OK to return NULL if the index was not changed at all during the
231+
<command>VACUUM</command> operation, but otherwise correct stats should
232+
be returned.
225233
</para>
226234

227235
<para>

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

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.1 2006/05/0211:28:54 teodor Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.2 2006/05/0222:25:10 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414

@@ -474,17 +474,25 @@ ginVacuumEntryPage(GinVacuumState *gvs, Buffer buffer, BlockNumber *roots, uint3
474474

475475
Datum
476476
ginbulkdelete(PG_FUNCTION_ARGS) {
477-
Relationindex= (Relation)PG_GETARG_POINTER(0);
478-
IndexBulkDeleteCallbackcallback= (IndexBulkDeleteCallback)PG_GETARG_POINTER(1);
479-
void*callback_state= (void*)PG_GETARG_POINTER(2);
477+
IndexVacuumInfo*info= (IndexVacuumInfo*)PG_GETARG_POINTER(0);
478+
IndexBulkDeleteResult*stats= (IndexBulkDeleteResult*)PG_GETARG_POINTER(1);
479+
IndexBulkDeleteCallbackcallback= (IndexBulkDeleteCallback)PG_GETARG_POINTER(2);
480+
void*callback_state= (void*)PG_GETARG_POINTER(3);
481+
Relationindex=info->index;
480482
BlockNumberblkno=GIN_ROOT_BLKNO;
481483
GinVacuumStategvs;
482484
Bufferbuffer;
483485
BlockNumberrootOfPostingTree[BLCKSZ/ (sizeof(IndexTupleData)+sizeof(ItemId)) ];
484486
uint32nRoot;
485487

488+
/* first time through? */
489+
if (stats==NULL)
490+
stats= (IndexBulkDeleteResult*)palloc0(sizeof(IndexBulkDeleteResult));
491+
/* we'll re-count the tuples each time */
492+
stats->num_index_tuples=0;
493+
486494
gvs.index=index;
487-
gvs.result=(IndexBulkDeleteResult*)palloc0(sizeof(IndexBulkDeleteResult));
495+
gvs.result=stats;
488496
gvs.callback=callback;
489497
gvs.callback_state=callback_state;
490498
initGinState(&gvs.ginstate,index);
@@ -564,9 +572,9 @@ ginbulkdelete(PG_FUNCTION_ARGS) {
564572

565573
Datum
566574
ginvacuumcleanup(PG_FUNCTION_ARGS) {
567-
Relationindex= (Relation)PG_GETARG_POINTER(0);
568-
IndexVacuumCleanupInfo*info= (IndexVacuumCleanupInfo*)PG_GETARG_POINTER(1);
569-
IndexBulkDeleteResult*stats= (IndexBulkDeleteResult*)PG_GETARG_POINTER(2);
575+
IndexVacuumInfo*info= (IndexVacuumInfo*)PG_GETARG_POINTER(0);
576+
IndexBulkDeleteResult*stats= (IndexBulkDeleteResult*)PG_GETARG_POINTER(1);
577+
Relationindex=info->index;
570578
boolneedLock= !RELATION_IS_LOCAL(index);
571579
BlockNumbernpages,
572580
blkno;
@@ -576,6 +584,15 @@ ginvacuumcleanup(PG_FUNCTION_ARGS) {
576584
BlockNumberlastBlock=GIN_ROOT_BLKNO,
577585
lastFilledBlock=GIN_ROOT_BLKNO;
578586

587+
/* Set up all-zero stats if ginbulkdelete wasn't called */
588+
if (stats==NULL)
589+
stats= (IndexBulkDeleteResult*)palloc0(sizeof(IndexBulkDeleteResult));
590+
/*
591+
* XXX we always report the heap tuple count as the number of index
592+
* entries. This is bogus if the index is partial, but it's real hard
593+
* to tell how many distinct heap entries are referenced by a GIN index.
594+
*/
595+
stats->num_index_tuples=info->num_heap_tuples;
579596

580597
if (info->vacuum_full) {
581598
LockRelation(index,AccessExclusiveLock);

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

Lines changed: 33 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.18 2006/03/31 23:32:05 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.19 2006/05/02 22:25:10 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -343,9 +343,9 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
343343
Datum
344344
gistvacuumcleanup(PG_FUNCTION_ARGS)
345345
{
346-
Relationrel= (Relation)PG_GETARG_POINTER(0);
347-
IndexVacuumCleanupInfo*info= (IndexVacuumCleanupInfo*)PG_GETARG_POINTER(1);
348-
GistBulkDeleteResult*stats= (GistBulkDeleteResult*)PG_GETARG_POINTER(2);
346+
IndexVacuumInfo*info= (IndexVacuumInfo*)PG_GETARG_POINTER(0);
347+
GistBulkDeleteResult*stats= (GistBulkDeleteResult*)PG_GETARG_POINTER(1);
348+
Relationrel=info->index;
349349
BlockNumbernpages,
350350
blkno;
351351
BlockNumbernFreePages,
@@ -355,6 +355,19 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
355355
lastFilledBlock=GIST_ROOT_BLKNO;
356356
boolneedLock;
357357

358+
/* Set up all-zero stats if gistbulkdelete wasn't called */
359+
if (stats==NULL)
360+
{
361+
stats= (GistBulkDeleteResult*)palloc0(sizeof(GistBulkDeleteResult));
362+
/* use heap's tuple count */
363+
Assert(info->num_heap_tuples >=0);
364+
stats->std.num_index_tuples=info->num_heap_tuples;
365+
/*
366+
* XXX the above is wrong if index is partial. Would it be OK to
367+
* just return NULL, or is there work we must do below?
368+
*/
369+
}
370+
358371
/* gistVacuumUpdate may cause hard work */
359372
if (info->vacuum_full)
360373
{
@@ -460,13 +473,6 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
460473
if (info->vacuum_full)
461474
UnlockRelation(rel,AccessExclusiveLock);
462475

463-
/* if gistbulkdelete skipped the scan, use heap's tuple count */
464-
if (stats->std.num_index_tuples<0)
465-
{
466-
Assert(info->num_heap_tuples >=0);
467-
stats->std.num_index_tuples=info->num_heap_tuples;
468-
}
469-
470476
PG_RETURN_POINTER(stats);
471477
}
472478

@@ -509,36 +515,22 @@ pushStackIfSplited(Page page, GistBDItem *stack)
509515
Datum
510516
gistbulkdelete(PG_FUNCTION_ARGS)
511517
{
512-
Relationrel= (Relation)PG_GETARG_POINTER(0);
513-
IndexBulkDeleteCallbackcallback= (IndexBulkDeleteCallback)PG_GETARG_POINTER(1);
514-
void*callback_state= (void*)PG_GETARG_POINTER(2);
515-
GistBulkDeleteResult*result;
518+
IndexVacuumInfo*info= (IndexVacuumInfo*)PG_GETARG_POINTER(0);
519+
GistBulkDeleteResult*stats= (GistBulkDeleteResult*)PG_GETARG_POINTER(1);
520+
IndexBulkDeleteCallbackcallback= (IndexBulkDeleteCallback)PG_GETARG_POINTER(2);
521+
void*callback_state= (void*)PG_GETARG_POINTER(3);
522+
Relationrel=info->index;
516523
GistBDItem*stack,
517524
*ptr;
518-
boolneedLock;
519525

520-
result= (GistBulkDeleteResult*)palloc0(sizeof(GistBulkDeleteResult));
526+
/* first time through? */
527+
if (stats==NULL)
528+
stats= (GistBulkDeleteResult*)palloc0(sizeof(GistBulkDeleteResult));
529+
/* we'll re-count the tuples each time */
530+
stats->std.num_index_tuples=0;
521531

522-
/*
523-
* We can skip the scan entirely if there's nothing to delete (indicated
524-
* by callback_state == NULL) and the index isn't partial. For a partial
525-
* index we must scan in order to derive a trustworthy tuple count.
526-
*
527-
* XXX as of PG 8.2 this is dead code because GIST indexes are always
528-
* effectively partial ... but keep it anyway in case our null-handling
529-
* gets fixed.
530-
*/
531-
if (callback_state||vac_is_partial_index(rel))
532-
{
533-
stack= (GistBDItem*)palloc0(sizeof(GistBDItem));
534-
stack->blkno=GIST_ROOT_BLKNO;
535-
}
536-
else
537-
{
538-
/* skip scan and set flag for gistvacuumcleanup */
539-
stack=NULL;
540-
result->std.num_index_tuples=-1;
541-
}
532+
stack= (GistBDItem*)palloc0(sizeof(GistBDItem));
533+
stack->blkno=GIST_ROOT_BLKNO;
542534

543535
while (stack)
544536
{
@@ -601,11 +593,11 @@ gistbulkdelete(PG_FUNCTION_ARGS)
601593
i--;
602594
maxoff--;
603595
ntodelete++;
604-
result->std.tuples_removed+=1;
596+
stats->std.tuples_removed+=1;
605597
Assert(maxoff==PageGetMaxOffsetNumber(page));
606598
}
607599
else
608-
result->std.num_index_tuples+=1;
600+
stats->std.num_index_tuples+=1;
609601
}
610602

611603
if (ntodelete)
@@ -658,7 +650,7 @@ gistbulkdelete(PG_FUNCTION_ARGS)
658650
stack->next=ptr;
659651

660652
if (GistTupleIsInvalid(idxtuple))
661-
result->needFullVacuum= true;
653+
stats->needFullVacuum= true;
662654
}
663655
}
664656

@@ -671,13 +663,5 @@ gistbulkdelete(PG_FUNCTION_ARGS)
671663
vacuum_delay_point();
672664
}
673665

674-
needLock= !RELATION_IS_LOCAL(rel);
675-
676-
if (needLock)
677-
LockRelationForExtension(rel,ExclusiveLock);
678-
result->std.num_pages=RelationGetNumberOfBlocks(rel);
679-
if (needLock)
680-
UnlockRelationForExtension(rel,ExclusiveLock);
681-
682-
PG_RETURN_POINTER(result);
666+
PG_RETURN_POINTER(stats);
683667
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp