~ubuntu-branches/ubuntu/trusty/postgresql-9.3/trusty-proposed

« back to all changes in this revision

Viewing changes to src/backend/utils/adt/selfuncs.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2016-03-31 11:04:53 UTC
  • mfrom: (1.1.11) (18.1.4 trusty-security)
  • Revision ID: package-import@ubuntu.com-20160331110453-h6xfs9f11suj3mze
Tags: 9.3.12-0ubuntu0.14.04
* New upstream bug fix release. (LP: #1564268)
  - See http://www.postgresql.org/about/news/1656/ for details.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4622
4622
 * *isdefault: set to TRUE if the result is a default rather than based on
4623
4623
 * anything meaningful.
4624
4624
 *
4625
 
 * NB: be careful to produce an integral result, since callers may compare
4626
 
 * the result to exact integer counts.
 
4625
 * NB: be careful to produce a positive integral result, since callers may
 
4626
 * compare the result to exact integer counts, or might divide by it.
4627
4627
 */
4628
4628
double
4629
4629
get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
4699
4699
         * If we had an absolute estimate, use that.
4700
4700
         */
4701
4701
        if (stadistinct > 0.0)
4702
 
                return stadistinct;
 
4702
                return clamp_row_est(stadistinct);
4703
4703
 
4704
4704
        /*
4705
4705
         * Otherwise we need to get the relation size; punt if not available.
4720
4720
         * If we had a relative estimate, use that.
4721
4721
         */
4722
4722
        if (stadistinct < 0.0)
4723
 
                return floor((-stadistinct * ntuples) + 0.5);
 
4723
                return clamp_row_est(-stadistinct * ntuples);
4724
4724
 
4725
4725
        /*
4726
4726
         * With no data, estimate ndistinct = ntuples if the table is small, else
4728
4728
         * that the behavior isn't discontinuous.
4729
4729
         */
4730
4730
        if (ntuples < DEFAULT_NUM_DISTINCT)
4731
 
                return ntuples;
 
4731
                return clamp_row_est(ntuples);
4732
4732
 
4733
4733
        *isdefault = true;
4734
4734
        return DEFAULT_NUM_DISTINCT;
7083
7083
                                numEntries;
7084
7084
        GinQualCounts counts;
7085
7085
        bool            matchPossible;
 
7086
        double          partialScale;
7086
7087
        double          entryPagesFetched,
7087
7088
                                dataPagesFetched,
7088
7089
                                dataPagesFetchedBySel;
7095
7096
        GinStatsData ginStats;
7096
7097
 
7097
7098
        /*
7098
 
         * Obtain statistic information from the meta page
 
7099
         * Obtain statistical information from the meta page, if possible.  Else
 
7100
         * set ginStats to zeroes, and we'll cope below.
7099
7101
         */
7100
 
        indexRel = index_open(index->indexoid, AccessShareLock);
7101
 
        ginGetStats(indexRel, &ginStats);
7102
 
        index_close(indexRel, AccessShareLock);
7103
 
 
7104
 
        numEntryPages = ginStats.nEntryPages;
7105
 
        numDataPages = ginStats.nDataPages;
7106
 
        numPendingPages = ginStats.nPendingPages;
7107
 
        numEntries = ginStats.nEntries;
 
7102
        if (!index->hypothetical)
 
7103
        {
 
7104
                indexRel = index_open(index->indexoid, AccessShareLock);
 
7105
                ginGetStats(indexRel, &ginStats);
 
7106
                index_close(indexRel, AccessShareLock);
 
7107
        }
 
7108
        else
 
7109
        {
 
7110
                memset(&ginStats, 0, sizeof(ginStats));
 
7111
        }
7108
7112
 
7109
7113
        /*
7110
 
         * nPendingPages can be trusted, but the other fields are as of the last
7111
 
         * VACUUM.  Scale them by the ratio numPages / nTotalPages to account for
7112
 
         * growth since then.  If the fields are zero (implying no VACUUM at all,
7113
 
         * and an index created pre-9.1), assume all pages are entry pages.
 
7114
         * Assuming we got valid (nonzero) stats at all, nPendingPages can be
 
7115
         * trusted, but the other fields are data as of the last VACUUM.  We can
 
7116
         * scale them up to account for growth since then, but that method only
 
7117
         * goes so far; in the worst case, the stats might be for a completely
 
7118
         * empty index, and scaling them will produce pretty bogus numbers.
 
7119
         * Somewhat arbitrarily, set the cutoff for doing scaling at 4X growth; if
 
7120
         * it's grown more than that, fall back to estimating things only from the
 
7121
         * assumed-accurate index size.  But we'll trust nPendingPages in any case
 
7122
         * so long as it's not clearly insane, ie, more than the index size.
7114
7123
         */
7115
 
        if (ginStats.nTotalPages == 0 || ginStats.nEntryPages == 0)
7116
 
        {
7117
 
                numEntryPages = numPages;
7118
 
                numDataPages = 0;
7119
 
                numEntries = numTuples; /* bogus, but no other info available */
7120
 
        }
 
7124
        if (ginStats.nPendingPages < numPages)
 
7125
                numPendingPages = ginStats.nPendingPages;
7121
7126
        else
 
7127
                numPendingPages = 0;
 
7128
 
 
7129
        if (numPages > 0 && ginStats.nTotalPages <= numPages &&
 
7130
                ginStats.nTotalPages > numPages / 4 &&
 
7131
                ginStats.nEntryPages > 0 && ginStats.nEntries > 0)
7122
7132
        {
 
7133
                /*
 
7134
                 * OK, the stats seem close enough to sane to be trusted.  But we
 
7135
                 * still need to scale them by the ratio numPages / nTotalPages to
 
7136
                 * account for growth since the last VACUUM.
 
7137
                 */
7123
7138
                double          scale = numPages / ginStats.nTotalPages;
7124
7139
 
7125
 
                numEntryPages = ceil(numEntryPages * scale);
7126
 
                numDataPages = ceil(numDataPages * scale);
7127
 
                numEntries = ceil(numEntries * scale);
 
7140
                numEntryPages = ceil(ginStats.nEntryPages * scale);
 
7141
                numDataPages = ceil(ginStats.nDataPages * scale);
 
7142
                numEntries = ceil(ginStats.nEntries * scale);
7128
7143
                /* ensure we didn't round up too much */
7129
 
                numEntryPages = Min(numEntryPages, numPages);
7130
 
                numDataPages = Min(numDataPages, numPages - numEntryPages);
 
7144
                numEntryPages = Min(numEntryPages, numPages - numPendingPages);
 
7145
                numDataPages = Min(numDataPages,
 
7146
                                                   numPages - numPendingPages - numEntryPages);
 
7147
        }
 
7148
        else
 
7149
        {
 
7150
                /*
 
7151
                 * We might get here because it's a hypothetical index, or an index
 
7152
                 * created pre-9.1 and never vacuumed since upgrading (in which case
 
7153
                 * its stats would read as zeroes), or just because it's grown too
 
7154
                 * much since the last VACUUM for us to put our faith in scaling.
 
7155
                 *
 
7156
                 * Invent some plausible internal statistics based on the index page
 
7157
                 * count (and clamp that to at least 10 pages, just in case).  We
 
7158
                 * estimate that 90% of the index is entry pages, and the rest is data
 
7159
                 * pages.  Estimate 100 entries per entry page; this is rather bogus
 
7160
                 * since it'll depend on the size of the keys, but it's more robust
 
7161
                 * than trying to predict the number of entries per heap tuple.
 
7162
                 */
 
7163
                numPages = Max(numPages, 10);
 
7164
                numEntryPages = floor((numPages - numPendingPages) * 0.90);
 
7165
                numDataPages = numPages - numPendingPages - numEntryPages;
 
7166
                numEntries = floor(numEntryPages * 100);
7131
7167
        }
7132
7168
 
7133
7169
        /* In an empty index, numEntries could be zero.  Avoid divide-by-zero */
7254
7290
        /*
7255
7291
         * Add an estimate of entry pages read by partial match algorithm. It's a
7256
7292
         * scan over leaf pages in entry tree.  We haven't any useful stats here,
7257
 
         * so estimate it as proportion.
 
7293
         * so estimate it as proportion.  Because counts.partialEntries is really
 
7294
         * pretty bogus (see code above), it's possible that it is more than
 
7295
         * numEntries; clamp the proportion to ensure sanity.
7258
7296
         */
7259
 
        entryPagesFetched += ceil(numEntryPages * counts.partialEntries / numEntries);
 
7297
        partialScale = counts.partialEntries / numEntries;
 
7298
        partialScale = Min(partialScale, 1.0);
 
7299
 
 
7300
        entryPagesFetched += ceil(numEntryPages * partialScale);
7260
7301
 
7261
7302
        /*
7262
7303
         * Partial match algorithm reads all data pages before doing actual scan,
7263
 
         * so it's a startup cost. Again, we haven't any useful stats here, so,
7264
 
         * estimate it as proportion
 
7304
         * so it's a startup cost.  Again, we haven't any useful stats here, so
 
7305
         * estimate it as proportion.
7265
7306
         */
7266
 
        dataPagesFetched = ceil(numDataPages * counts.partialEntries / numEntries);
 
7307
        dataPagesFetched = ceil(numDataPages * partialScale);
7267
7308
 
7268
7309
        /*
7269
7310
         * Calculate cache effects if more than one scan due to nestloops or array