1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Add gin_clean_pending_list function to clean up GIN pending list

This function cleans up the pending list of the GIN index by
moving entries in it to the main GIN data structure in bulk.
It returns the number of pages cleaned up from the pending list.

This function is useful, for example, when the pending list
needs to be cleaned up *quickly* to improve the performance of
the search using GIN index. VACUUM can do the same thing, too,
but it may take days to run on a large table.

Jeff Janes,
reviewed by Julien Rouhaud, Jaime Casanova, Alvaro Herrera and me.

Discussion: CAMkU=1x8zFkpfnozXyt40zmR3Ub_kHu58LtRmwHUKRgQss7=iQ@mail.gmail.com
This commit is contained in:
Fujii Masao
2016-01-28 12:57:52 +09:00
parent eaf7b1f643
commit 7f46eaf035
9 changed files with 108 additions and 4 deletions

View File

@ -20,10 +20,13 @@
#include "access/gin_private.h"
#include "access/xloginsert.h"
#include "access/xlog.h"
#include "commands/vacuum.h"
#include "catalog/pg_am.h"
#include "miscadmin.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/acl.h"
#include "storage/indexfsm.h"
/* GUC parameter */
@ -958,3 +961,52 @@ ginInsertCleanup(GinState *ginstate,
MemoryContextSwitchTo(oldCtx);
MemoryContextDelete(opCtx);
}
/*
* SQL-callable function to clean the insert pending list
*/
Datum
gin_clean_pending_list(PG_FUNCTION_ARGS)
{
Oid indexoid = PG_GETARG_OID(0);
Relation indexRel = index_open(indexoid, AccessShareLock);
IndexBulkDeleteResult stats;
GinState ginstate;
if (RecoveryInProgress())
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("recovery is in progress"),
errhint("GIN pending list cannot be cleaned up during recovery.")));
/* Must be a GIN index */
if (indexRel->rd_rel->relkind != RELKIND_INDEX ||
indexRel->rd_rel->relam != GIN_AM_OID)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a GIN index",
RelationGetRelationName(indexRel))));
/*
* Reject attempts to read non-local temporary relations; we would be
* likely to get wrong data since we have no visibility into the owning
* session's local buffers.
*/
if (RELATION_IS_OTHER_TEMP(indexRel))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot access temporary indexes of other sessions")));
/* User must own the index (comparable to privileges needed for VACUUM) */
if (!pg_class_ownercheck(indexoid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
RelationGetRelationName(indexRel));
memset(&stats, 0, sizeof(stats));
initGinState(&ginstate, indexRel);
ginInsertCleanup(&ginstate, true, &stats);
index_close(indexRel, AccessShareLock);
PG_RETURN_INT64((int64) stats.pages_deleted);
}