本文共 7347 字,大约阅读时间需要 24 分钟。
再次回到 estimate_rel_size 我发现,
在入口参数 rel中, rel->rd_rel->reltuples 的值已经完全准备好了:/* * estimate_rel_size - estimate # pages and # tuples in a table or index * * We also estimate the fraction of the pages that are marked all-visible in * the visibility map, for use in estimation of index-only scans. * * If attr_widths isn't NULL, it points to the zero-index entry of the * relation's attr_widths[] cache; we fill this in if we have need to compute * the attribute widths for estimation purposes. */voidestimate_rel_size(Relation rel, int32 *attr_widths, BlockNumber *pages, double *tuples, double *allvisfrac){ BlockNumber curpages; BlockNumber relpages; double reltuples; BlockNumber relallvisible; double density; switch (rel->rd_rel->relkind) { case RELKIND_RELATION: case RELKIND_INDEX: case RELKIND_TOASTVALUE: fprintf(stderr,"In %s...(double) rel->rd_rel->reltuples is: %lf by process %d\n\n",__FUNCTION__, (double) rel->rd_rel->reltuples, getpid()); /* it has storage, ok to call the smgr */ curpages = RelationGetNumberOfBlocks(rel); //fprintf(stderr,"In %s...(double) rel->rd_rel->reltuples is: %lf by process %d\n\n",__FUNCTION__, (double) rel->rd_rel->reltuples, getpid()); /* * HACK: if the relation has never yet been vacuumed, use a * minimum size estimate of 10 pages. The idea here is to avoid * assuming a newly-created table is really small, even if it * currently is, because that may not be true once some data gets * loaded into it. Once a vacuum or analyze cycle has been done * on it, it's more reasonable to believe the size is somewhat * stable. * * (Note that this is only an issue if the plan gets cached and * used again after the table has been filled. What we're trying * to avoid is using a nestloop-type plan on a table that has * grown substantially since the plan was made. Normally, * autovacuum/autoanalyze will occur once enough inserts have * happened and cause cached-plan invalidation; but that doesn't * happen instantaneously, and it won't happen at all for cases * such as temporary tables.) * * We approximate "never vacuumed" by "has relpages = 0", which * means this will also fire on genuinely empty relations. Not * great, but fortunately that's a seldom-seen case in the real * world, and it shouldn't degrade the quality of the plan too * much anyway to err in this direction. * * There are two exceptions wherein we don't apply this heuristic. * One is if the table has inheritance children. Totally empty * parent tables are quite common, so we should be willing to * believe that they are empty. Also, we don't apply the 10-page * minimum to indexes. */ if (curpages < 10 && rel->rd_rel->relpages == 0 && !rel->rd_rel->relhassubclass && rel->rd_rel->relkind != RELKIND_INDEX) curpages = 10; /* report estimated # pages */ *pages = curpages; /* quick exit if rel is clearly empty */ if (curpages == 0) { *tuples = 0; *allvisfrac = 0; break; } /* coerce values in pg_class to more desirable types */ relpages = (BlockNumber) rel->rd_rel->relpages; reltuples = (double) rel->rd_rel->reltuples; //fprintf(stderr,"In %s...reltuples is: %lf\n by process %d", __FUNCTION__,reltuples, getpid()); relallvisible = (BlockNumber) rel->rd_rel->relallvisible; /* * If it's an index, discount the metapage while estimating the * number of tuples. This is a kluge because it assumes more than * it ought to about index structure. Currently it's OK for * btree, hash, and GIN indexes but suspect for GiST indexes. */ if (rel->rd_rel->relkind == RELKIND_INDEX && relpages > 0) { curpages--; relpages--; } /* estimate number of tuples from previous tuple density */ if (relpages > 0) density = reltuples / (double) relpages; else { /* * When we have no data because the relation was truncated, * estimate tuple width from attribute datatypes. We assume * here that the pages are completely full, which is OK for * tables (since they've presumably not been VACUUMed yet) but * is probably an overestimate for indexes. Fortunately * get_relation_info() can clamp the overestimate to the * parent table's size. * * Note: this code intentionally disregards alignment * considerations, because (a) that would be gilding the lily * considering how crude the estimate is, and (b) it creates * platform dependencies in the default plans which are kind * of a headache for regression testing. */ int32 tuple_width; tuple_width = get_rel_data_width(rel, attr_widths); tuple_width += sizeof(HeapTupleHeaderData); tuple_width += sizeof(ItemPointerData); /* note: integer division is intentional here */ density = (BLCKSZ - SizeOfPageHeaderData) / tuple_width; } *tuples = rint(density * (double) curpages); //fprintf(stderr,"In %s...*tuples is: %lf\n by process %d", __FUNCTION__,*tuples, getpid()); /* * We use relallvisible as-is, rather than scaling it up like we * do for the pages and tuples counts, on the theory that any * pages added since the last VACUUM are most likely not marked * all-visible. But costsize.c wants it converted to a fraction. */ if (relallvisible == 0 || curpages <= 0) *allvisfrac = 0; else if ((double) relallvisible >= curpages) *allvisfrac = 1; else *allvisfrac = (double) relallvisible / curpages; break; case RELKIND_SEQUENCE: /* Sequences always have a known size */ *pages = 1; *tuples = 1; *allvisfrac = 0; break; case RELKIND_FOREIGN_TABLE: /* Just use whatever's in pg_class */ *pages = rel->rd_rel->relpages; *tuples = rel->rd_rel->reltuples; *allvisfrac = 0; break; default: /* else it has no disk storage; probably shouldn't get here? */ *pages = 0; *tuples = 0; *allvisfrac = 0; break; }}
然后,需要回溯到上一个层面,查找源头。
本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2013/05/28/3103594.html,如需转载请自行联系原作者