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:
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user