diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2012-04-06 16:04:10 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2012-04-06 16:04:10 -0400 |
commit | cea49fe82fedcf125eb99a780099eaf47a326b03 (patch) | |
tree | 37312e107b898d1dc4668f52bf2eb9876f18fbce /src | |
parent | 263d9de66b867b7800fac82c222e004b795b724a (diff) | |
download | postgresql-cea49fe82fedcf125eb99a780099eaf47a326b03.tar.gz postgresql-cea49fe82fedcf125eb99a780099eaf47a326b03.zip |
Dept of second thoughts: improve the API for AnalyzeForeignTable.
If we make the initially-called function return the table physical-size
estimate, acquire_inherited_sample_rows will be able to use that to
allocate numbers of samples among child tables, when the day comes that
we want to support foreign tables in inheritance trees.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/commands/analyze.c | 94 | ||||
-rw-r--r-- | src/include/foreign/fdwapi.h | 8 |
2 files changed, 46 insertions, 56 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 17abe48f25e..ff271644e0f 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -84,7 +84,8 @@ static BufferAccessStrategy vac_strategy; static void do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, - AcquireSampleRowsFunc acquirefunc, bool inh, int elevel); + AcquireSampleRowsFunc acquirefunc, BlockNumber relpages, + bool inh, int elevel); static void BlockSampler_Init(BlockSampler bs, BlockNumber nblocks, int samplesize); static bool BlockSampler_HasMore(BlockSampler bs); @@ -97,8 +98,7 @@ static VacAttrStats *examine_attribute(Relation onerel, int attnum, Node *index_expr); static int acquire_sample_rows(Relation onerel, int elevel, HeapTuple *rows, int targrows, - double *totalrows, double *totaldeadrows, - BlockNumber *totalpages); + double *totalrows, double *totaldeadrows); static int compare_rows(const void *a, const void *b); static int acquire_inherited_sample_rows(Relation onerel, int elevel, HeapTuple *rows, int targrows, @@ -117,7 +117,8 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, BufferAccessStrategy bstrategy) { Relation onerel; int elevel; - AcquireSampleRowsFunc acquirefunc; + AcquireSampleRowsFunc acquirefunc = NULL; + BlockNumber relpages = 0; /* Select logging level */ if (vacstmt->options & VACOPT_VERBOSE) @@ -183,6 +184,27 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, BufferAccessStrategy bstrategy) } /* + * Silently ignore tables that are temp tables of other backends --- + * trying to analyze these is rather pointless, since their contents are + * probably not up-to-date on disk. (We don't throw a warning here; it + * would just lead to chatter during a database-wide ANALYZE.) + */ + if (RELATION_IS_OTHER_TEMP(onerel)) + { + relation_close(onerel, ShareUpdateExclusiveLock); + return; + } + + /* + * We can ANALYZE any table except pg_statistic. See update_attstats + */ + if (RelationGetRelid(onerel) == StatisticRelationId) + { + relation_close(onerel, ShareUpdateExclusiveLock); + return; + } + + /* * Check that it's a plain table or foreign table; we used to do this * in get_rel_oids() but seems safer to check after we've locked the * relation. @@ -191,6 +213,8 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, BufferAccessStrategy bstrategy) { /* Regular table, so we'll use the regular row acquisition function */ acquirefunc = acquire_sample_rows; + /* Also get regular table's size */ + relpages = RelationGetNumberOfBlocks(onerel); } else if (onerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) { @@ -199,15 +223,16 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, BufferAccessStrategy bstrategy) * supports analysis. */ FdwRoutine *fdwroutine; + bool ok = false; fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(onerel)); if (fdwroutine->AnalyzeForeignTable != NULL) - acquirefunc = fdwroutine->AnalyzeForeignTable(onerel); - else - acquirefunc = NULL; + ok = fdwroutine->AnalyzeForeignTable(onerel, + &acquirefunc, + &relpages); - if (acquirefunc == NULL) + if (!ok) { ereport(WARNING, (errmsg("skipping \"%s\" --- cannot analyze this foreign table", @@ -228,27 +253,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, BufferAccessStrategy bstrategy) } /* - * Silently ignore tables that are temp tables of other backends --- - * trying to analyze these is rather pointless, since their contents are - * probably not up-to-date on disk. (We don't throw a warning here; it - * would just lead to chatter during a database-wide ANALYZE.) - */ - if (RELATION_IS_OTHER_TEMP(onerel)) - { - relation_close(onerel, ShareUpdateExclusiveLock); - return; - } - - /* - * We can ANALYZE any table except pg_statistic. See update_attstats - */ - if (RelationGetRelid(onerel) == StatisticRelationId) - { - relation_close(onerel, ShareUpdateExclusiveLock); - return; - } - - /* * OK, let's do it. First let other backends know I'm in ANALYZE. */ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); @@ -258,13 +262,13 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, BufferAccessStrategy bstrategy) /* * Do the normal non-recursive ANALYZE. */ - do_analyze_rel(onerel, vacstmt, acquirefunc, false, elevel); + do_analyze_rel(onerel, vacstmt, acquirefunc, relpages, false, elevel); /* * If there are child tables, do recursive ANALYZE. */ if (onerel->rd_rel->relhassubclass) - do_analyze_rel(onerel, vacstmt, acquirefunc, true, elevel); + do_analyze_rel(onerel, vacstmt, acquirefunc, relpages, true, elevel); /* * Close source relation now, but keep lock so that no one deletes it @@ -293,7 +297,8 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, BufferAccessStrategy bstrategy) */ static void do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, - AcquireSampleRowsFunc acquirefunc, bool inh, int elevel) + AcquireSampleRowsFunc acquirefunc, BlockNumber relpages, + bool inh, int elevel) { int attr_cnt, tcnt, @@ -308,7 +313,6 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, numrows; double totalrows, totaldeadrows; - BlockNumber totalpages; HeapTuple *rows; PGRUsage ru0; TimestampTz starttime = 0; @@ -485,17 +489,13 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, */ rows = (HeapTuple *) palloc(targrows * sizeof(HeapTuple)); if (inh) - { numrows = acquire_inherited_sample_rows(onerel, elevel, rows, targrows, &totalrows, &totaldeadrows); - totalpages = 0; /* not needed in this path */ - } else numrows = (*acquirefunc) (onerel, elevel, rows, targrows, - &totalrows, &totaldeadrows, - &totalpages); + &totalrows, &totaldeadrows); /* * Compute the statistics. Temporary results during the calculations for @@ -576,7 +576,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt, */ if (!inh) vac_update_relstats(onerel, - totalpages, + relpages, totalrows, visibilitymap_count(onerel), hasindex, @@ -1032,7 +1032,6 @@ BlockSampler_Next(BlockSampler bs) * The actual number of rows selected is returned as the function result. * We also estimate the total numbers of live and dead rows in the table, * and return them into *totalrows and *totaldeadrows, respectively. - * Also, the number of pages in the relation is returned into *totalpages. * * The returned list of tuples is in order by physical position in the table. * (We will rely on this later to derive correlation estimates.) @@ -1061,8 +1060,7 @@ BlockSampler_Next(BlockSampler bs) static int acquire_sample_rows(Relation onerel, int elevel, HeapTuple *rows, int targrows, - double *totalrows, double *totaldeadrows, - BlockNumber *totalpages) + double *totalrows, double *totaldeadrows) { int numrows = 0; /* # rows now in reservoir */ double samplerows = 0; /* total # rows collected */ @@ -1077,7 +1075,6 @@ acquire_sample_rows(Relation onerel, int elevel, Assert(targrows > 0); totalblocks = RelationGetNumberOfBlocks(onerel); - *totalpages = totalblocks; /* Need a cutoff xmin for HeapTupleSatisfiesVacuum */ OldestXmin = GetOldestXmin(onerel->rd_rel->relisshared, true); @@ -1438,7 +1435,7 @@ compare_rows(const void *a, const void *b) /* * acquire_inherited_sample_rows -- acquire sample rows from inheritance tree * - * This has largely the same API as acquire_sample_rows, except that rows are + * This has the same API as acquire_sample_rows, except that rows are * collected from all inheritance children as well as the specified table. * We fail and return zero if there are no inheritance children. */ @@ -1481,11 +1478,6 @@ acquire_inherited_sample_rows(Relation onerel, int elevel, /* * Count the blocks in all the relations. The result could overflow * BlockNumber, so we use double arithmetic. - * - * XXX eventually we will probably want to allow child tables that are - * foreign tables. Since we can't do RelationGetNumberOfBlocks on a - * foreign table, it's not very clear what fraction of the total to assign - * to it here. */ rels = (Relation *) palloc(list_length(tableOIDs) * sizeof(Relation)); relblocks = (double *) palloc(list_length(tableOIDs) * sizeof(double)); @@ -1540,7 +1532,6 @@ acquire_inherited_sample_rows(Relation onerel, int elevel, int childrows; double trows, tdrows; - BlockNumber tpages; /* Fetch a random sample of the child's rows */ childrows = acquire_sample_rows(childrel, @@ -1548,8 +1539,7 @@ acquire_inherited_sample_rows(Relation onerel, int elevel, rows + numrows, childtargrows, &trows, - &tdrows, - &tpages); + &tdrows); /* We may need to convert from child's rowtype to parent's */ if (childrows > 0 && diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h index 6bf3a5e2306..0a09c949326 100644 --- a/src/include/foreign/fdwapi.h +++ b/src/include/foreign/fdwapi.h @@ -53,11 +53,11 @@ typedef void (*EndForeignScan_function) (ForeignScanState *node); typedef int (*AcquireSampleRowsFunc) (Relation relation, int elevel, HeapTuple *rows, int targrows, double *totalrows, - double *totaldeadrows, - BlockNumber *totalpages); - -typedef AcquireSampleRowsFunc (*AnalyzeForeignTable_function) (Relation relation); + double *totaldeadrows); +typedef bool (*AnalyzeForeignTable_function) (Relation relation, + AcquireSampleRowsFunc *func, + BlockNumber *totalpages); /* * FdwRoutine is the struct returned by a foreign-data wrapper's handler |