/* * Returns true iff the given segment file should be compacted. */ bool AppendOnlyCompaction_ShouldCompact( Relation aoRelation, AppendOnlyEntry *aoEntry, int segno, int64 segmentTotalTupcount, bool isFull) { bool result; AppendOnlyVisimap visiMap; int64 hiddenTupcount; int hideRatio; Assert(RelationIsAoRows(aoRelation) || RelationIsAoCols(aoRelation)); if (!gp_appendonly_compaction) { ereport(LOG, (errmsg("Append-only compaction skipped on relation %s, segment file num %d", RelationGetRelationName(aoRelation), segno), errdetail("Compaction is disabled"))); /* Disable compaction by global guc. */ return false; } AppendOnlyVisimap_Init(&visiMap, aoEntry->visimaprelid, aoEntry->visimapidxid, ShareLock, SnapshotNow); hiddenTupcount = AppendOnlyVisimap_GetSegmentFileHiddenTupleCount( &visiMap, segno); result = true; if (isFull && hiddenTupcount > 0) { /* * if it is a full vacuum and there is any obsolete data, do a compaction */ result = true; } else { hideRatio = AppendOnlyCompaction_GetHideRatio(hiddenTupcount, segmentTotalTupcount); if (hideRatio <= gp_appendonly_compaction_threshold || gp_appendonly_compaction_threshold == 0) { if (hiddenTupcount > 0) { ereportif(Debug_appendonly_print_compaction, LOG, (errmsg("Append-only compaction skipped on relation %s, segment file num %d, " "hidden tupcount " INT64_FORMAT ", total tupcount " INT64_FORMAT ", " "hide ratio %d%%, threshold %d%%", RelationGetRelationName(aoRelation), segno, hiddenTupcount, segmentTotalTupcount, hideRatio, gp_appendonly_compaction_threshold))); ereport(LOG, (errmsg("Append-only compaction skipped on relation %s, segment file num %d", RelationGetRelationName(aoRelation), segno), errdetail("Ratio of obsolete tuples below threshold (%d%% vs %d%%)", hideRatio, gp_appendonly_compaction_threshold))); } else { ereportif(Debug_appendonly_print_compaction, LOG, (errmsg("Append-only compaction skipped on relation %s, segment file num %d, " "hidden tupcount " INT64_FORMAT ", total tupcount " INT64_FORMAT ", " "hide ratio %d%%, threshold %d%%", RelationGetRelationName(aoRelation), segno, hiddenTupcount, segmentTotalTupcount, hideRatio, gp_appendonly_compaction_threshold))); } result = false; } elogif(Debug_appendonly_print_compaction, LOG, "Schedule compaction: " "segno %d, " "hidden tupcount " INT64_FORMAT ", total tupcount " INT64_FORMAT ", " "hide ratio %d%%, threshold %d%%", segno, hiddenTupcount, segmentTotalTupcount, hideRatio, gp_appendonly_compaction_threshold); } AppendOnlyVisimap_Finish(&visiMap, ShareLock); return result; }
static Datum gp_aovisimap_hidden_info_internal(PG_FUNCTION_ARGS, Oid aoRelOid) { Datum values[3]; bool nulls[3]; HeapTuple tuple; Datum result; typedef struct Context { AppendOnlyVisimap visiMap; Relation parentRelation; FileSegInfo **appendonlySegfileInfo; AOCSFileSegInfo **aocsSegfileInfo; int segfile_info_total; int i; } Context; FuncCallContext *funcctx; Context *context; if (SRF_IS_FIRSTCALL()) { TupleDesc tupdesc; MemoryContext oldcontext; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* * switch to memory context appropriate for multiple function * calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* build tupdesc for result tuples */ tupdesc = CreateTemplateTupleDesc(3, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "segno", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "hidden_tupcount", INT8OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "total_tupcount", INT8OID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); /* * Collect all the locking information that we will format and send * out as a result set. */ context = (Context *) palloc0(sizeof(Context)); context->parentRelation = heap_open(aoRelOid, AccessShareLock); if (!(RelationIsAoRows(context->parentRelation) || RelationIsAoCols(context->parentRelation))) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Function not supported on relation"))); } if (RelationIsAoRows(context->parentRelation)) { context->appendonlySegfileInfo = GetAllFileSegInfo( context->parentRelation, SnapshotNow, &context->segfile_info_total); } else { Assert(RelationIsAoCols(context->parentRelation)); context->aocsSegfileInfo = GetAllAOCSFileSegInfo(context->parentRelation, SnapshotNow, &context->segfile_info_total); } context->i = 0; AppendOnlyVisimap_Init(&context->visiMap, context->parentRelation->rd_appendonly->visimaprelid, context->parentRelation->rd_appendonly->visimapidxid, AccessShareLock, SnapshotNow); funcctx->user_fctx = (void *) context; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); context = (Context *) funcctx->user_fctx; while (context->i < context->segfile_info_total) { int64 tupcount; int segno; if (context->appendonlySegfileInfo) { FileSegInfo *fsinfo = context->appendonlySegfileInfo[context->i]; tupcount = fsinfo->total_tupcount; segno = fsinfo->segno; } else if (context->aocsSegfileInfo) { AOCSFileSegInfo *fsinfo = context->aocsSegfileInfo[context->i]; tupcount = fsinfo->total_tupcount; segno = fsinfo->segno; } else { Insist(false); } MemSet(values, 0, sizeof(values)); MemSet(nulls, false, sizeof(nulls)); values[0] = Int32GetDatum(segno); values[1] = Int64GetDatum(AppendOnlyVisimap_GetSegmentFileHiddenTupleCount( &context->visiMap, segno)); values[2] = Int64GetDatum(tupcount); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); context->i++; SRF_RETURN_NEXT(funcctx, result); } AppendOnlyVisimap_Finish(&context->visiMap, AccessShareLock); if (context->appendonlySegfileInfo) { FreeAllSegFileInfo(context->appendonlySegfileInfo, context->segfile_info_total); pfree(context->appendonlySegfileInfo); context->appendonlySegfileInfo = NULL; } if (context->aocsSegfileInfo) { FreeAllAOCSSegFileInfo(context->aocsSegfileInfo, context->segfile_info_total); pfree(context->aocsSegfileInfo); context->aocsSegfileInfo = NULL; } heap_close(context->parentRelation, AccessShareLock); pfree(context); funcctx->user_fctx = NULL; SRF_RETURN_DONE(funcctx); }