diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 7d0a5ce30d..ca6996e448 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -2089,103 +2089,19 @@ do_autovacuum(void) continue; } - if (classForm->relkind == RELKIND_RELATION || - classForm->relkind == RELKIND_MATVIEW) - { - /* Fetch reloptions and the pgstat entry for this table */ - relopts = extract_autovac_opts(tuple, pg_class_desc); - tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared, - shared, dbentry); - - /* Check if it needs vacuum or analyze */ - relation_needs_vacanalyze(relid, relopts, classForm, tabentry, - effective_multixact_freeze_max_age, - &dovacuum, &doanalyze, &wraparound); - - /* Relations that need work are added to table_oids */ - if (dovacuum || doanalyze) - table_oids = lappend_oid(table_oids, relid); - } - else - { - /* - * If the relation is a partitioned table, we check it using reltuples - * added up childrens' and changes_since_analyze tracked by stats collector. - * We check only auto analyze because partitioned tables don't need to vacuum. - */ - List *tableOIDs; - ListCell *lc; - bool av_enabled; - int anl_base_thresh; - float4 all_reltuples = 0, - anl_scale_factor, - anlthresh, - reltuples, - anltuples; - - /* Find all members of inheritance set taking AccessShareLock */ - tableOIDs = find_all_inheritors(relid, AccessShareLock, NULL); - - foreach(lc, tableOIDs) - { - Oid childOID = lfirst_oid(lc); - HeapTuple childtuple; - Form_pg_class childclassForm; - - /* Ignore the parent table */ - if (childOID == relid) - continue; - - childtuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(childOID)); - childclassForm = (Form_pg_class) GETSTRUCT(childtuple); - - /* Skip foreign partitions */ - if (childclassForm->relkind == RELKIND_FOREIGN_TABLE) - continue; - - /* Sum up the child's reltuples for its parent table */ - all_reltuples += childclassForm->reltuples; - elog(NOTICE, "[parent:%s] child%s has %.0f tuples", NameStr(classForm->relname),NameStr(childclassForm->relname), childclassForm->reltuples); - } - - - /* Fetch reloptions and the pgstat entry for the partitioned table */ - relopts = extract_autovac_opts(tuple, pg_class_desc); - tabentry = get_pgstat_tabentry_relid(relid, - classForm->relisshared, - shared, dbentry); - - /* Check if it needs auto analyze */ - av_enabled = (relopts ? relopts->enabled : true); - - if (av_enabled) - { - anl_scale_factor = (relopts && relopts->analyze_scale_factor >= 0) - ? relopts->analyze_scale_factor - : autovacuum_anl_scale; - - anl_base_thresh = (relopts && relopts->analyze_threshold >= 0) - ? relopts->analyze_threshold - : autovacuum_anl_thresh; - - elog(NOTICE, "[parent:%s] has %.0f tuples", NameStr(classForm->relname), all_reltuples); - if (PointerIsValid(tabentry)) - { - reltuples = all_reltuples; - anltuples = tabentry->changes_since_analyze; - anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples; + /* Fetch reloptions and the pgstat entry for this table */ + relopts = extract_autovac_opts(tuple, pg_class_desc); + tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared, + shared, dbentry); - elog(DEBUG3, "%s: anl: %.0f (threshold %.0f)", - NameStr(classForm->relname), - anltuples, anlthresh); + /* Check if it needs vacuum or analyze */ + relation_needs_vacanalyze(relid, relopts, classForm, tabentry, + effective_multixact_freeze_max_age, + &dovacuum, &doanalyze, &wraparound); - /* Determine if this table needs analyze. */ - doanalyze = (anltuples > anlthresh); - } - if (doanalyze) - table_oids = lappend_oid(table_oids, relid); - } - } + /* Relations that need work are added to table_oids */ + if (dovacuum || doanalyze) + table_oids = lappend_oid(table_oids, relid); /* * Remember TOAST associations for the second pass. Note: we must do @@ -2880,105 +2796,33 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, return NULL; classForm = (Form_pg_class) GETSTRUCT(classTup); - if (classForm->relkind != RELKIND_PARTITIONED_TABLE) + /* + * Get the applicable reloptions. If it is a TOAST table, try to get the + * main table reloptions if the toast table itself doesn't have. + */ + avopts = extract_autovac_opts(classTup, pg_class_desc); + if (classForm->relkind == RELKIND_TOASTVALUE && + avopts == NULL && table_toast_map != NULL) { - /* - * Get the applicable reloptions. If it is a TOAST table, try to get the - * main table reloptions if the toast table itself doesn't have. - */ - avopts = extract_autovac_opts(classTup, pg_class_desc); - if (classForm->relkind == RELKIND_TOASTVALUE && - avopts == NULL && table_toast_map != NULL) - { - av_relation *hentry; - bool found; - - hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); - if (found && hentry->ar_hasrelopts) - avopts = &hentry->ar_reloptions; - } - - /* fetch the pgstat table entry */ - tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared, - shared, dbentry); - - relation_needs_vacanalyze(relid, avopts, classForm, tabentry, - effective_multixact_freeze_max_age, - &dovacuum, &doanalyze, &wraparound); + av_relation *hentry; + bool found; - /* ignore ANALYZE for toast tables */ - if (classForm->relkind == RELKIND_TOASTVALUE) - doanalyze = false; + hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found); + if (found && hentry->ar_hasrelopts) + avopts = &hentry->ar_reloptions; } - else - { - List *tableOIDs; - ListCell *lc; - bool av_enabled; - int anl_base_thresh; - float4 all_reltuples, - anl_scale_factor, - anlthresh, - reltuples, - anltuples; - /* Find all members of inheritance set taking AccessShareLock */ - tableOIDs = find_all_inheritors(relid, AccessShareLock, NULL); + /* fetch the pgstat table entry */ + tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared, + shared, dbentry); - foreach(lc, tableOIDs) - { - Oid childOID = lfirst_oid(lc); - HeapTuple childtuple; - Form_pg_class childclassForm; + relation_needs_vacanalyze(relid, avopts, classForm, tabentry, + effective_multixact_freeze_max_age, + &dovacuum, &doanalyze, &wraparound); - /* Ignore the parent table */ - if (childOID == relid) - continue; - - childtuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(childOID)); - childclassForm = (Form_pg_class) GETSTRUCT(childtuple); - - /* Skip foreign partitions */ - if (childclassForm->relkind == RELKIND_FOREIGN_TABLE) - continue; - - /* Sum up the child's reltuples for the partitioned table */ - all_reltuples += childclassForm->reltuples; - } - - /* Fetch reloptions and the pgstat entry for the partitioned table */ - avopts = extract_autovac_opts(classTup, pg_class_desc); - tabentry = get_pgstat_tabentry_relid(relid, - classForm->relisshared, - shared, dbentry); - - /* Check if it needs auto analyze */ - av_enabled = (avopts ? avopts->enabled : true); - - if (av_enabled) - { - anl_scale_factor = (avopts && avopts->analyze_scale_factor >= 0) - ? avopts->analyze_scale_factor - : autovacuum_anl_scale; - - anl_base_thresh = (avopts && avopts->analyze_threshold >= 0) - ? avopts->analyze_threshold - : autovacuum_anl_thresh; - - if (PointerIsValid(tabentry)) - { - reltuples = all_reltuples; - anltuples = tabentry->changes_since_analyze; - anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples; - - elog(DEBUG3, "%s: anl: %.0f (threshold %.0f)", - NameStr(classForm->relname), - anltuples, anlthresh); - - doanalyze = (anltuples > anlthresh); - } - } - } + /* ignore ANALYZE for toast tables */ + if (classForm->relkind == RELKIND_TOASTVALUE) + doanalyze = false; /* OK, it needs something done */ if (doanalyze || dovacuum) @@ -3148,6 +2992,42 @@ relation_needs_vacanalyze(Oid relid, AssertArg(classForm != NULL); AssertArg(OidIsValid(relid)); + /* + * If the relation is a partitioned table, we must add up children's + * reltuples. + */ + if (classForm->relkind == RELKIND_PARTITIONED_TABLE) + { + List *children; + ListCell *lc; + + reltuples = 0; + + /* Find all members of inheritance set taking AccessShareLock */ + children = find_all_inheritors(relid, AccessShareLock, NULL); + + foreach(lc, children) + { + Oid childOID = lfirst_oid(lc); + HeapTuple childtuple; + Form_pg_class childclass; + + /* Ignore the parent table */ + if (childOID == relid) + continue; + + childtuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(childOID)); + childclass = (Form_pg_class) GETSTRUCT(childtuple); + + /* Skip foreign partitions */ + if (childclass->relkind == RELKIND_FOREIGN_TABLE) + continue; + + /* Sum up the child's reltuples for its parent table */ + reltuples += childclass->reltuples; + } + } + /* * Determine vacuum/analyze equation parameters. We have two possible * sources: the passed reloptions (which could be a main table or a toast