8000 Make gincostestimate() cope with hypothetical GIN indexes. · SudhirLonkar/postgres@7882143 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7882143

Browse files
committed
Make gincostestimate() cope with hypothetical GIN indexes.
We tried to fetch statistics data from the index metapage, which does not work if the index isn't actually present. If the index is hypothetical, instead extrapolate some plausible internal statistics based on the index page count provided by the index-advisor plugin. There was already some code in gincostestimate() to invent internal stats in this way, but since it was only meant as a stopgap for pre-9.1 GIN indexes that hadn't been vacuumed since upgrading, it was pretty crude. If we want it to support index advisors, we should try a little harder. A small amount of testing says that it's better to estimate the entry pages as 90% of the index, not 100%. Also, estimating the number of entries (keys) as equal to the heap tuple count could be wildly wrong in either direction. Instead, let's estimate 100 entries per entry page. Perhaps someday somebody will want the index advisor to be able to provide these numbers more directly, but for the moment this should serve. Problem report and initial patch by Julien Rouhaud; modified by me to invent less-bogus internal statistics. Back-patch to all supported branches, since we've supported index advisors since 9.0.
1 parent 8438749 commit 7882143

File tree

1 file changed

+38
-20
lines changed

1 file changed

+38
-20
lines changed

src/backend/utils/adt/selfuncs.c

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6618,40 +6618,58 @@ gincostestimate(PG_FUNCTION_ARGS)
66186618
GinStatsData ginStats;
66196619

66206620
/*
6621-
* Obtain statistic information from the meta page
6621+
* Obtain statistical information from the meta page, if possible. Else
6622+
* set ginStats to zeroes, and we'll cope below.
66226623
*/
6623-
indexRel = index_open(index->indexoid, AccessShareLock);
6624-
ginGetStats(indexRel, &ginStats);
6625-
index_close(indexRel, AccessShareLock);
6626-
6627-
numEntryPages = ginStats.nEntryPages;
6628-
numDataPages = ginStats.nDataPages;
6629-
numPendingPages = ginStats.nPendingPages;
6630-
numEntries = ginStats.nEntries;
6631-
6632-
/*
6633-
* nPendingPages can be trusted, but the other fields are as of the last
6634-
* VACUUM. Scale them by the ratio numPages / nTotalPages to account for
6635-
* growth since then. If the fields are zero (implying no VACUUM at all,
6636-
* and an index created pre-9.1), assume all pages are entry pages.
6637-
*/
6638-
if (ginStats.nTotalPages == 0 || ginStats.nEntryPages == 0)
6624+
if (!index->hypothetical)
66396625
{
6640-
numEntryPages = numPages;
6641-
numDataPages = 0;
6642-
numEntries = numTuples; /* bogus, but no other info available */
6626+
indexRel = index_open(index->indexoid, AccessShareLock);
6627+
ginGetStats(indexRel, &ginStats);
6628+
index_close(indexRel, AccessShareLock);
66436629
}
66446630
else
66456631
{
6632+
memset(&ginStats, 0, sizeof(ginStats));
6633+
}
6634+
6635+
if (ginStats.nTotalPages > 0 && ginStats.nEntryPages > 0 && numPages > 0)
6636+
{
6637+
/*
6638+
* We got valid stats. nPendingPages can be trusted, but the other
6639+
* fields are data as of the last VACUUM. Scale them by the ratio
6640+
* numPages / nTotalPages to account for growth since then.
6641+
*/
66466642
double scale = numPages / ginStats.nTotalPages;
66476643

6644+
numEntryPages = ginStats.nEntryPages;
6645+
numDataPages = ginStats.nDataPages;
6646+
numPendingPages = ginStats.nPendingPages;
6647+
numEntries = ginStats.nEntries;
6648+
66486649
numEntryPages = ceil(numEntryPages * scale);
66496650
numDataPages = ceil(numDataPages * scale);
66506651
numEntries = ceil(numEntries * scale);
66516652
/* ensure we didn't round up too much */
66526653
numEntryPages = Min(numEntryPages, numPages);
66536654
numDataPages = Min(numDataPages, numPages - numEntryPages);
66546655
}
6656+
else
6657+
{
6658+
/*
6659+
* It's a hypothetical index, or perhaps an index created pre-9.1 and
6660+
* never vacuumed since upgrading. Invent some plausible internal
6661+
* statistics based on the index page count. We estimate that 90% of
6662+
* the index is entry pages, and the rest is data pages. Estimate 100
6663+
* entries per entry page; this is rather bogus since it'll depend on
6664+
* the size of the keys, but it's more robust than trying to predict
6665+
* the number of entries per heap tuple.
6666+
*/
6667+
numPages = Max(numPages, 10);
6668+
numEntryPages = floor(numPages * 0.90);
6669+
numDataPages = numPages - numEntryPages;
6670+
numPendingPages = 0;
6671+
numEntries = floor(numEntryPages * 100);
6672+
}
66556673

66566674
/* In an empty index, numEntries could be zero. Avoid divide-by-zero */
66576675
if (numEntries < 1)

0 commit comments

Comments
 (0)
0