From d7f00aa0c35d29c41af8f2c4068725e8eeb5f82c Mon Sep 17 00:00:00 2001 From: ejrh Date: Tue, 27 Nov 2018 20:31:58 +1300 Subject: [PATCH 5/5] TID selectivity: reduce the density of the last page by half This takes into account the fact that the last page will have only half the density, on average, as other pages in a table. --- src/backend/utils/adt/selfuncs.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index f5a1ee0..e7ed9a5 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -604,8 +604,18 @@ scalarineqsel(PlannerInfo *root, Oid operator, bool isgt, bool iseq, * assume there will never be any dead tuples or empty space at * the start or in the middle of the page. This is likely fine * for the purposes here. + * + * Since the last page will, on average, be only half full, we can + * estimate it to have half as many tuples as earlier pages. So + * give it half the weight of a regular page. */ - density = vardata->rel->tuples / vardata->rel->pages; + density = vardata->rel->tuples / (vardata->rel->pages - 0.5); + + /* If it's the last page, it has half the density. */ + if (block >= vardata->rel->pages - 1) + density *= 0.5; + + /* Add a fraction of a block to take the offset into account. */ if (density > 0.0) { OffsetNumber offset = ItemPointerGetOffsetNumberNoCheck(itemptr); @@ -613,7 +623,11 @@ scalarineqsel(PlannerInfo *root, Oid operator, bool isgt, bool iseq, block += Min(offset / density, 1.0); } - selec = block / (double) vardata->rel->pages; + /* + * Again, the last page has only half weight when converting the + * relative block number to a selectivity. + */ + selec = block / (vardata->rel->pages - 0.5); /* * We'll have one less tuple for "<" and one additional tuple for -- 2.7.4