~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/commands/analyze.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * analyze.c
 
4
 *        the Postgres statistics generator
 
5
 *
 
6
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        src/backend/commands/analyze.c
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
#include "postgres.h"
 
16
 
 
17
#include <math.h>
 
18
 
 
19
#include "access/heapam.h"
 
20
#include "access/transam.h"
 
21
#include "access/tupconvert.h"
 
22
#include "access/tuptoaster.h"
 
23
#include "access/xact.h"
 
24
#include "catalog/index.h"
 
25
#include "catalog/indexing.h"
 
26
#include "catalog/namespace.h"
 
27
#include "catalog/pg_collation.h"
 
28
#include "catalog/pg_inherits_fn.h"
 
29
#include "catalog/pg_namespace.h"
 
30
#include "commands/dbcommands.h"
 
31
#include "commands/vacuum.h"
 
32
#include "executor/executor.h"
 
33
#include "miscadmin.h"
 
34
#include "nodes/nodeFuncs.h"
 
35
#include "parser/parse_oper.h"
 
36
#include "parser/parse_relation.h"
 
37
#include "pgstat.h"
 
38
#include "postmaster/autovacuum.h"
 
39
#include "storage/bufmgr.h"
 
40
#include "storage/lmgr.h"
 
41
#include "storage/proc.h"
 
42
#include "storage/procarray.h"
 
43
#include "utils/acl.h"
 
44
#include "utils/attoptcache.h"
 
45
#include "utils/datum.h"
 
46
#include "utils/guc.h"
 
47
#include "utils/lsyscache.h"
 
48
#include "utils/memutils.h"
 
49
#include "utils/pg_rusage.h"
 
50
#include "utils/syscache.h"
 
51
#include "utils/tuplesort.h"
 
52
#include "utils/tqual.h"
 
53
 
 
54
 
 
55
/* Data structure for Algorithm S from Knuth 3.4.2 */
 
56
typedef struct
 
57
{
 
58
        BlockNumber N;                          /* number of blocks, known in advance */
 
59
        int                     n;                              /* desired sample size */
 
60
        BlockNumber t;                          /* current block number */
 
61
        int                     m;                              /* blocks selected so far */
 
62
} BlockSamplerData;
 
63
 
 
64
typedef BlockSamplerData *BlockSampler;
 
65
 
 
66
/* Per-index data for ANALYZE */
 
67
typedef struct AnlIndexData
 
68
{
 
69
        IndexInfo  *indexInfo;          /* BuildIndexInfo result */
 
70
        double          tupleFract;             /* fraction of rows for partial index */
 
71
        VacAttrStats **vacattrstats;    /* index attrs to analyze */
 
72
        int                     attr_cnt;
 
73
} AnlIndexData;
 
74
 
 
75
 
 
76
/* Default statistics target (GUC parameter) */
 
77
int                     default_statistics_target = 100;
 
78
 
 
79
/* A few variables that don't seem worth passing around as parameters */
 
80
static int      elevel = -1;
 
81
 
 
82
static MemoryContext anl_context = NULL;
 
83
 
 
84
static BufferAccessStrategy vac_strategy;
 
85
 
 
86
 
 
87
static void do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
 
88
                           bool update_reltuples, bool inh);
 
89
static void BlockSampler_Init(BlockSampler bs, BlockNumber nblocks,
 
90
                                  int samplesize);
 
91
static bool BlockSampler_HasMore(BlockSampler bs);
 
92
static BlockNumber BlockSampler_Next(BlockSampler bs);
 
93
static void compute_index_stats(Relation onerel, double totalrows,
 
94
                                        AnlIndexData *indexdata, int nindexes,
 
95
                                        HeapTuple *rows, int numrows,
 
96
                                        MemoryContext col_context);
 
97
static VacAttrStats *examine_attribute(Relation onerel, int attnum,
 
98
                                  Node *index_expr);
 
99
static int acquire_sample_rows(Relation onerel, HeapTuple *rows,
 
100
                                        int targrows, double *totalrows, double *totaldeadrows);
 
101
static double random_fract(void);
 
102
static double init_selection_state(int n);
 
103
static double get_next_S(double t, int n, double *stateptr);
 
104
static int      compare_rows(const void *a, const void *b);
 
105
static int acquire_inherited_sample_rows(Relation onerel,
 
106
                                                          HeapTuple *rows, int targrows,
 
107
                                                          double *totalrows, double *totaldeadrows);
 
108
static void update_attstats(Oid relid, bool inh,
 
109
                                int natts, VacAttrStats **vacattrstats);
 
110
static Datum std_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
 
111
static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
 
112
 
 
113
static bool std_typanalyze(VacAttrStats *stats);
 
114
 
 
115
 
 
116
/*
 
117
 *      analyze_rel() -- analyze one relation
 
118
 *
 
119
 * If update_reltuples is true, we update reltuples and relpages columns
 
120
 * in pg_class.  Caller should pass false if we're part of VACUUM ANALYZE,
 
121
 * and the VACUUM didn't skip any pages.  We only have an approximate count,
 
122
 * so we don't want to overwrite the accurate values already inserted by the
 
123
 * VACUUM in that case.  VACUUM always scans all indexes, however, so the
 
124
 * pg_class entries for indexes are never updated if we're part of VACUUM
 
125
 * ANALYZE.
 
126
 */
 
127
void
 
128
analyze_rel(Oid relid, VacuumStmt *vacstmt,
 
129
                        BufferAccessStrategy bstrategy, bool update_reltuples)
 
130
{
 
131
        Relation        onerel;
 
132
 
 
133
        /* Set up static variables */
 
134
        if (vacstmt->options & VACOPT_VERBOSE)
 
135
                elevel = INFO;
 
136
        else
 
137
                elevel = DEBUG2;
 
138
 
 
139
        vac_strategy = bstrategy;
 
140
 
 
141
        /*
 
142
         * Check for user-requested abort.
 
143
         */
 
144
        CHECK_FOR_INTERRUPTS();
 
145
 
 
146
        /*
 
147
         * Open the relation, getting ShareUpdateExclusiveLock to ensure that two
 
148
         * ANALYZEs don't run on it concurrently.  (This also locks out a
 
149
         * concurrent VACUUM, which doesn't matter much at the moment but might
 
150
         * matter if we ever try to accumulate stats on dead tuples.) If the rel
 
151
         * has been dropped since we last saw it, we don't need to process it.
 
152
         */
 
153
        if (!(vacstmt->options & VACOPT_NOWAIT))
 
154
                onerel = try_relation_open(relid, ShareUpdateExclusiveLock);
 
155
        else if (ConditionalLockRelationOid(relid, ShareUpdateExclusiveLock))
 
156
                onerel = try_relation_open(relid, NoLock);
 
157
        else
 
158
        {
 
159
                onerel = NULL;
 
160
                if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
 
161
                        ereport(LOG,
 
162
                                        (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
 
163
                                  errmsg("skipping analyze of \"%s\" --- lock not available",
 
164
                                                 vacstmt->relation->relname)));
 
165
        }
 
166
        if (!onerel)
 
167
                return;
 
168
 
 
169
        /*
 
170
         * Check permissions --- this should match vacuum's check!
 
171
         */
 
172
        if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
 
173
                  (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
 
174
        {
 
175
                /* No need for a WARNING if we already complained during VACUUM */
 
176
                if (!(vacstmt->options & VACOPT_VACUUM))
 
177
                {
 
178
                        if (onerel->rd_rel->relisshared)
 
179
                                ereport(WARNING,
 
180
                                 (errmsg("skipping \"%s\" --- only superuser can analyze it",
 
181
                                                 RelationGetRelationName(onerel))));
 
182
                        else if (onerel->rd_rel->relnamespace == PG_CATALOG_NAMESPACE)
 
183
                                ereport(WARNING,
 
184
                                                (errmsg("skipping \"%s\" --- only superuser or database owner can analyze it",
 
185
                                                                RelationGetRelationName(onerel))));
 
186
                        else
 
187
                                ereport(WARNING,
 
188
                                                (errmsg("skipping \"%s\" --- only table or database owner can analyze it",
 
189
                                                                RelationGetRelationName(onerel))));
 
190
                }
 
191
                relation_close(onerel, ShareUpdateExclusiveLock);
 
192
                return;
 
193
        }
 
194
 
 
195
        /*
 
196
         * Check that it's a plain table; we used to do this in get_rel_oids() but
 
197
         * seems safer to check after we've locked the relation.
 
198
         */
 
199
        if (onerel->rd_rel->relkind != RELKIND_RELATION)
 
200
        {
 
201
                /* No need for a WARNING if we already complained during VACUUM */
 
202
                if (!(vacstmt->options & VACOPT_VACUUM))
 
203
                        ereport(WARNING,
 
204
                                        (errmsg("skipping \"%s\" --- cannot analyze non-tables or special system tables",
 
205
                                                        RelationGetRelationName(onerel))));
 
206
                relation_close(onerel, ShareUpdateExclusiveLock);
 
207
                return;
 
208
        }
 
209
 
 
210
        /*
 
211
         * Silently ignore tables that are temp tables of other backends ---
 
212
         * trying to analyze these is rather pointless, since their contents are
 
213
         * probably not up-to-date on disk.  (We don't throw a warning here; it
 
214
         * would just lead to chatter during a database-wide ANALYZE.)
 
215
         */
 
216
        if (RELATION_IS_OTHER_TEMP(onerel))
 
217
        {
 
218
                relation_close(onerel, ShareUpdateExclusiveLock);
 
219
                return;
 
220
        }
 
221
 
 
222
        /*
 
223
         * We can ANALYZE any table except pg_statistic. See update_attstats
 
224
         */
 
225
        if (RelationGetRelid(onerel) == StatisticRelationId)
 
226
        {
 
227
                relation_close(onerel, ShareUpdateExclusiveLock);
 
228
                return;
 
229
        }
 
230
 
 
231
        /*
 
232
         * OK, let's do it.  First let other backends know I'm in ANALYZE.
 
233
         */
 
234
        LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
 
235
        MyProc->vacuumFlags |= PROC_IN_ANALYZE;
 
236
        LWLockRelease(ProcArrayLock);
 
237
 
 
238
        /*
 
239
         * Do the normal non-recursive ANALYZE.
 
240
         */
 
241
        do_analyze_rel(onerel, vacstmt, update_reltuples, false);
 
242
 
 
243
        /*
 
244
         * If there are child tables, do recursive ANALYZE.
 
245
         */
 
246
        if (onerel->rd_rel->relhassubclass)
 
247
                do_analyze_rel(onerel, vacstmt, false, true);
 
248
 
 
249
        /*
 
250
         * Close source relation now, but keep lock so that no one deletes it
 
251
         * before we commit.  (If someone did, they'd fail to clean up the entries
 
252
         * we made in pg_statistic.  Also, releasing the lock before commit would
 
253
         * expose us to concurrent-update failures in update_attstats.)
 
254
         */
 
255
        relation_close(onerel, NoLock);
 
256
 
 
257
        /*
 
258
         * Reset my PGPROC flag.  Note: we need this here, and not in vacuum_rel,
 
259
         * because the vacuum flag is cleared by the end-of-xact code.
 
260
         */
 
261
        LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
 
262
        MyProc->vacuumFlags &= ~PROC_IN_ANALYZE;
 
263
        LWLockRelease(ProcArrayLock);
 
264
}
 
265
 
 
266
/*
 
267
 *      do_analyze_rel() -- analyze one relation, recursively or not
 
268
 */
 
269
static void
 
270
do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
 
271
                           bool update_reltuples, bool inh)
 
272
{
 
273
        int                     attr_cnt,
 
274
                                tcnt,
 
275
                                i,
 
276
                                ind;
 
277
        Relation   *Irel;
 
278
        int                     nindexes;
 
279
        bool            hasindex;
 
280
        bool            analyzableindex;
 
281
        VacAttrStats **vacattrstats;
 
282
        AnlIndexData *indexdata;
 
283
        int                     targrows,
 
284
                                numrows;
 
285
        double          totalrows,
 
286
                                totaldeadrows;
 
287
        HeapTuple  *rows;
 
288
        PGRUsage        ru0;
 
289
        TimestampTz starttime = 0;
 
290
        MemoryContext caller_context;
 
291
        Oid                     save_userid;
 
292
        int                     save_sec_context;
 
293
        int                     save_nestlevel;
 
294
 
 
295
        if (inh)
 
296
                ereport(elevel,
 
297
                                (errmsg("analyzing \"%s.%s\" inheritance tree",
 
298
                                                get_namespace_name(RelationGetNamespace(onerel)),
 
299
                                                RelationGetRelationName(onerel))));
 
300
        else
 
301
                ereport(elevel,
 
302
                                (errmsg("analyzing \"%s.%s\"",
 
303
                                                get_namespace_name(RelationGetNamespace(onerel)),
 
304
                                                RelationGetRelationName(onerel))));
 
305
 
 
306
        /*
 
307
         * Set up a working context so that we can easily free whatever junk gets
 
308
         * created.
 
309
         */
 
310
        anl_context = AllocSetContextCreate(CurrentMemoryContext,
 
311
                                                                                "Analyze",
 
312
                                                                                ALLOCSET_DEFAULT_MINSIZE,
 
313
                                                                                ALLOCSET_DEFAULT_INITSIZE,
 
314
                                                                                ALLOCSET_DEFAULT_MAXSIZE);
 
315
        caller_context = MemoryContextSwitchTo(anl_context);
 
316
 
 
317
        /*
 
318
         * Switch to the table owner's userid, so that any index functions are run
 
319
         * as that user.  Also lock down security-restricted operations and
 
320
         * arrange to make GUC variable changes local to this command.
 
321
         */
 
322
        GetUserIdAndSecContext(&save_userid, &save_sec_context);
 
323
        SetUserIdAndSecContext(onerel->rd_rel->relowner,
 
324
                                                   save_sec_context | SECURITY_RESTRICTED_OPERATION);
 
325
        save_nestlevel = NewGUCNestLevel();
 
326
 
 
327
        /* measure elapsed time iff autovacuum logging requires it */
 
328
        if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
 
329
        {
 
330
                pg_rusage_init(&ru0);
 
331
                if (Log_autovacuum_min_duration > 0)
 
332
                        starttime = GetCurrentTimestamp();
 
333
        }
 
334
 
 
335
        /*
 
336
         * Determine which columns to analyze
 
337
         *
 
338
         * Note that system attributes are never analyzed.
 
339
         */
 
340
        if (vacstmt->va_cols != NIL)
 
341
        {
 
342
                ListCell   *le;
 
343
 
 
344
                vacattrstats = (VacAttrStats **) palloc(list_length(vacstmt->va_cols) *
 
345
                                                                                                sizeof(VacAttrStats *));
 
346
                tcnt = 0;
 
347
                foreach(le, vacstmt->va_cols)
 
348
                {
 
349
                        char       *col = strVal(lfirst(le));
 
350
 
 
351
                        i = attnameAttNum(onerel, col, false);
 
352
                        if (i == InvalidAttrNumber)
 
353
                                ereport(ERROR,
 
354
                                                (errcode(ERRCODE_UNDEFINED_COLUMN),
 
355
                                        errmsg("column \"%s\" of relation \"%s\" does not exist",
 
356
                                                   col, RelationGetRelationName(onerel))));
 
357
                        vacattrstats[tcnt] = examine_attribute(onerel, i, NULL);
 
358
                        if (vacattrstats[tcnt] != NULL)
 
359
                                tcnt++;
 
360
                }
 
361
                attr_cnt = tcnt;
 
362
        }
 
363
        else
 
364
        {
 
365
                attr_cnt = onerel->rd_att->natts;
 
366
                vacattrstats = (VacAttrStats **)
 
367
                        palloc(attr_cnt * sizeof(VacAttrStats *));
 
368
                tcnt = 0;
 
369
                for (i = 1; i <= attr_cnt; i++)
 
370
                {
 
371
                        vacattrstats[tcnt] = examine_attribute(onerel, i, NULL);
 
372
                        if (vacattrstats[tcnt] != NULL)
 
373
                                tcnt++;
 
374
                }
 
375
                attr_cnt = tcnt;
 
376
        }
 
377
 
 
378
        /*
 
379
         * Open all indexes of the relation, and see if there are any analyzable
 
380
         * columns in the indexes.      We do not analyze index columns if there was
 
381
         * an explicit column list in the ANALYZE command, however.  If we are
 
382
         * doing a recursive scan, we don't want to touch the parent's indexes at
 
383
         * all.
 
384
         */
 
385
        if (!inh)
 
386
                vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
 
387
        else
 
388
        {
 
389
                Irel = NULL;
 
390
                nindexes = 0;
 
391
        }
 
392
        hasindex = (nindexes > 0);
 
393
        indexdata = NULL;
 
394
        analyzableindex = false;
 
395
        if (hasindex)
 
396
        {
 
397
                indexdata = (AnlIndexData *) palloc0(nindexes * sizeof(AnlIndexData));
 
398
                for (ind = 0; ind < nindexes; ind++)
 
399
                {
 
400
                        AnlIndexData *thisdata = &indexdata[ind];
 
401
                        IndexInfo  *indexInfo;
 
402
 
 
403
                        thisdata->indexInfo = indexInfo = BuildIndexInfo(Irel[ind]);
 
404
                        thisdata->tupleFract = 1.0; /* fix later if partial */
 
405
                        if (indexInfo->ii_Expressions != NIL && vacstmt->va_cols == NIL)
 
406
                        {
 
407
                                ListCell   *indexpr_item = list_head(indexInfo->ii_Expressions);
 
408
 
 
409
                                thisdata->vacattrstats = (VacAttrStats **)
 
410
                                        palloc(indexInfo->ii_NumIndexAttrs * sizeof(VacAttrStats *));
 
411
                                tcnt = 0;
 
412
                                for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
 
413
                                {
 
414
                                        int                     keycol = indexInfo->ii_KeyAttrNumbers[i];
 
415
 
 
416
                                        if (keycol == 0)
 
417
                                        {
 
418
                                                /* Found an index expression */
 
419
                                                Node       *indexkey;
 
420
 
 
421
                                                if (indexpr_item == NULL)               /* shouldn't happen */
 
422
                                                        elog(ERROR, "too few entries in indexprs list");
 
423
                                                indexkey = (Node *) lfirst(indexpr_item);
 
424
                                                indexpr_item = lnext(indexpr_item);
 
425
                                                thisdata->vacattrstats[tcnt] =
 
426
                                                        examine_attribute(Irel[ind], i + 1, indexkey);
 
427
                                                if (thisdata->vacattrstats[tcnt] != NULL)
 
428
                                                {
 
429
                                                        tcnt++;
 
430
                                                        analyzableindex = true;
 
431
                                                }
 
432
                                        }
 
433
                                }
 
434
                                thisdata->attr_cnt = tcnt;
 
435
                        }
 
436
                }
 
437
        }
 
438
 
 
439
        /*
 
440
         * Quit if no analyzable columns and no pg_class update needed.
 
441
         */
 
442
        if (attr_cnt <= 0 && !analyzableindex && !update_reltuples)
 
443
                goto cleanup;
 
444
 
 
445
        /*
 
446
         * Determine how many rows we need to sample, using the worst case from
 
447
         * all analyzable columns.      We use a lower bound of 100 rows to avoid
 
448
         * possible overflow in Vitter's algorithm.
 
449
         */
 
450
        targrows = 100;
 
451
        for (i = 0; i < attr_cnt; i++)
 
452
        {
 
453
                if (targrows < vacattrstats[i]->minrows)
 
454
                        targrows = vacattrstats[i]->minrows;
 
455
        }
 
456
        for (ind = 0; ind < nindexes; ind++)
 
457
        {
 
458
                AnlIndexData *thisdata = &indexdata[ind];
 
459
 
 
460
                for (i = 0; i < thisdata->attr_cnt; i++)
 
461
                {
 
462
                        if (targrows < thisdata->vacattrstats[i]->minrows)
 
463
                                targrows = thisdata->vacattrstats[i]->minrows;
 
464
                }
 
465
        }
 
466
 
 
467
        /*
 
468
         * Acquire the sample rows
 
469
         */
 
470
        rows = (HeapTuple *) palloc(targrows * sizeof(HeapTuple));
 
471
        if (inh)
 
472
                numrows = acquire_inherited_sample_rows(onerel, rows, targrows,
 
473
                                                                                                &totalrows, &totaldeadrows);
 
474
        else
 
475
                numrows = acquire_sample_rows(onerel, rows, targrows,
 
476
                                                                          &totalrows, &totaldeadrows);
 
477
 
 
478
        /*
 
479
         * Compute the statistics.      Temporary results during the calculations for
 
480
         * each column are stored in a child context.  The calc routines are
 
481
         * responsible to make sure that whatever they store into the VacAttrStats
 
482
         * structure is allocated in anl_context.
 
483
         */
 
484
        if (numrows > 0)
 
485
        {
 
486
                MemoryContext col_context,
 
487
                                        old_context;
 
488
 
 
489
                col_context = AllocSetContextCreate(anl_context,
 
490
                                                                                        "Analyze Column",
 
491
                                                                                        ALLOCSET_DEFAULT_MINSIZE,
 
492
                                                                                        ALLOCSET_DEFAULT_INITSIZE,
 
493
                                                                                        ALLOCSET_DEFAULT_MAXSIZE);
 
494
                old_context = MemoryContextSwitchTo(col_context);
 
495
 
 
496
                for (i = 0; i < attr_cnt; i++)
 
497
                {
 
498
                        VacAttrStats *stats = vacattrstats[i];
 
499
                        AttributeOpts *aopt =
 
500
                        get_attribute_options(onerel->rd_id, stats->attr->attnum);
 
501
 
 
502
                        stats->rows = rows;
 
503
                        stats->tupDesc = onerel->rd_att;
 
504
                        (*stats->compute_stats) (stats,
 
505
                                                                         std_fetch_func,
 
506
                                                                         numrows,
 
507
                                                                         totalrows);
 
508
 
 
509
                        /*
 
510
                         * If the appropriate flavor of the n_distinct option is
 
511
                         * specified, override with the corresponding value.
 
512
                         */
 
513
                        if (aopt != NULL)
 
514
                        {
 
515
                                float8          n_distinct =
 
516
                                inh ? aopt->n_distinct_inherited : aopt->n_distinct;
 
517
 
 
518
                                if (n_distinct != 0.0)
 
519
                                        stats->stadistinct = n_distinct;
 
520
                        }
 
521
 
 
522
                        MemoryContextResetAndDeleteChildren(col_context);
 
523
                }
 
524
 
 
525
                if (hasindex)
 
526
                        compute_index_stats(onerel, totalrows,
 
527
                                                                indexdata, nindexes,
 
528
                                                                rows, numrows,
 
529
                                                                col_context);
 
530
 
 
531
                MemoryContextSwitchTo(old_context);
 
532
                MemoryContextDelete(col_context);
 
533
 
 
534
                /*
 
535
                 * Emit the completed stats rows into pg_statistic, replacing any
 
536
                 * previous statistics for the target columns.  (If there are stats in
 
537
                 * pg_statistic for columns we didn't process, we leave them alone.)
 
538
                 */
 
539
                update_attstats(RelationGetRelid(onerel), inh,
 
540
                                                attr_cnt, vacattrstats);
 
541
 
 
542
                for (ind = 0; ind < nindexes; ind++)
 
543
                {
 
544
                        AnlIndexData *thisdata = &indexdata[ind];
 
545
 
 
546
                        update_attstats(RelationGetRelid(Irel[ind]), false,
 
547
                                                        thisdata->attr_cnt, thisdata->vacattrstats);
 
548
                }
 
549
        }
 
550
 
 
551
        /*
 
552
         * Update pages/tuples stats in pg_class, but not if we're inside a VACUUM
 
553
         * that got a more precise number.
 
554
         */
 
555
        if (update_reltuples)
 
556
                vac_update_relstats(onerel,
 
557
                                                        RelationGetNumberOfBlocks(onerel),
 
558
                                                        totalrows, hasindex, InvalidTransactionId);
 
559
 
 
560
        /*
 
561
         * Same for indexes. Vacuum always scans all indexes, so if we're part of
 
562
         * VACUUM ANALYZE, don't overwrite the accurate count already inserted by
 
563
         * VACUUM.
 
564
         */
 
565
        if (!(vacstmt->options & VACOPT_VACUUM))
 
566
        {
 
567
                for (ind = 0; ind < nindexes; ind++)
 
568
                {
 
569
                        AnlIndexData *thisdata = &indexdata[ind];
 
570
                        double          totalindexrows;
 
571
 
 
572
                        totalindexrows = ceil(thisdata->tupleFract * totalrows);
 
573
                        vac_update_relstats(Irel[ind],
 
574
                                                                RelationGetNumberOfBlocks(Irel[ind]),
 
575
                                                                totalindexrows, false, InvalidTransactionId);
 
576
                }
 
577
        }
 
578
 
 
579
        /*
 
580
         * Report ANALYZE to the stats collector, too; likewise, tell it to adopt
 
581
         * these numbers only if we're not inside a VACUUM that got a better
 
582
         * number.      However, a call with inh = true shouldn't reset the stats.
 
583
         */
 
584
        if (!inh)
 
585
                pgstat_report_analyze(onerel, update_reltuples,
 
586
                                                          totalrows, totaldeadrows);
 
587
 
 
588
        /* We skip to here if there were no analyzable columns */
 
589
cleanup:
 
590
 
 
591
        /* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
 
592
        if (!(vacstmt->options & VACOPT_VACUUM))
 
593
        {
 
594
                for (ind = 0; ind < nindexes; ind++)
 
595
                {
 
596
                        IndexBulkDeleteResult *stats;
 
597
                        IndexVacuumInfo ivinfo;
 
598
 
 
599
                        ivinfo.index = Irel[ind];
 
600
                        ivinfo.analyze_only = true;
 
601
                        ivinfo.estimated_count = true;
 
602
                        ivinfo.message_level = elevel;
 
603
                        ivinfo.num_heap_tuples = onerel->rd_rel->reltuples;
 
604
                        ivinfo.strategy = vac_strategy;
 
605
 
 
606
                        stats = index_vacuum_cleanup(&ivinfo, NULL);
 
607
 
 
608
                        if (stats)
 
609
                                pfree(stats);
 
610
                }
 
611
        }
 
612
 
 
613
        /* Done with indexes */
 
614
        vac_close_indexes(nindexes, Irel, NoLock);
 
615
 
 
616
        /* Log the action if appropriate */
 
617
        if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
 
618
        {
 
619
                if (Log_autovacuum_min_duration == 0 ||
 
620
                        TimestampDifferenceExceeds(starttime, GetCurrentTimestamp(),
 
621
                                                                           Log_autovacuum_min_duration))
 
622
                        ereport(LOG,
 
623
                                        (errmsg("automatic analyze of table \"%s.%s.%s\" system usage: %s",
 
624
                                                        get_database_name(MyDatabaseId),
 
625
                                                        get_namespace_name(RelationGetNamespace(onerel)),
 
626
                                                        RelationGetRelationName(onerel),
 
627
                                                        pg_rusage_show(&ru0))));
 
628
        }
 
629
 
 
630
        /* Roll back any GUC changes executed by index functions */
 
631
        AtEOXact_GUC(false, save_nestlevel);
 
632
 
 
633
        /* Restore userid and security context */
 
634
        SetUserIdAndSecContext(save_userid, save_sec_context);
 
635
 
 
636
        /* Restore current context and release memory */
 
637
        MemoryContextSwitchTo(caller_context);
 
638
        MemoryContextDelete(anl_context);
 
639
        anl_context = NULL;
 
640
}
 
641
 
 
642
/*
 
643
 * Compute statistics about indexes of a relation
 
644
 */
 
645
static void
 
646
compute_index_stats(Relation onerel, double totalrows,
 
647
                                        AnlIndexData *indexdata, int nindexes,
 
648
                                        HeapTuple *rows, int numrows,
 
649
                                        MemoryContext col_context)
 
650
{
 
651
        MemoryContext ind_context,
 
652
                                old_context;
 
653
        Datum           values[INDEX_MAX_KEYS];
 
654
        bool            isnull[INDEX_MAX_KEYS];
 
655
        int                     ind,
 
656
                                i;
 
657
 
 
658
        ind_context = AllocSetContextCreate(anl_context,
 
659
                                                                                "Analyze Index",
 
660
                                                                                ALLOCSET_DEFAULT_MINSIZE,
 
661
                                                                                ALLOCSET_DEFAULT_INITSIZE,
 
662
                                                                                ALLOCSET_DEFAULT_MAXSIZE);
 
663
        old_context = MemoryContextSwitchTo(ind_context);
 
664
 
 
665
        for (ind = 0; ind < nindexes; ind++)
 
666
        {
 
667
                AnlIndexData *thisdata = &indexdata[ind];
 
668
                IndexInfo  *indexInfo = thisdata->indexInfo;
 
669
                int                     attr_cnt = thisdata->attr_cnt;
 
670
                TupleTableSlot *slot;
 
671
                EState     *estate;
 
672
                ExprContext *econtext;
 
673
                List       *predicate;
 
674
                Datum      *exprvals;
 
675
                bool       *exprnulls;
 
676
                int                     numindexrows,
 
677
                                        tcnt,
 
678
                                        rowno;
 
679
                double          totalindexrows;
 
680
 
 
681
                /* Ignore index if no columns to analyze and not partial */
 
682
                if (attr_cnt == 0 && indexInfo->ii_Predicate == NIL)
 
683
                        continue;
 
684
 
 
685
                /*
 
686
                 * Need an EState for evaluation of index expressions and
 
687
                 * partial-index predicates.  Create it in the per-index context to be
 
688
                 * sure it gets cleaned up at the bottom of the loop.
 
689
                 */
 
690
                estate = CreateExecutorState();
 
691
                econtext = GetPerTupleExprContext(estate);
 
692
                /* Need a slot to hold the current heap tuple, too */
 
693
                slot = MakeSingleTupleTableSlot(RelationGetDescr(onerel));
 
694
 
 
695
                /* Arrange for econtext's scan tuple to be the tuple under test */
 
696
                econtext->ecxt_scantuple = slot;
 
697
 
 
698
                /* Set up execution state for predicate. */
 
699
                predicate = (List *)
 
700
                        ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
 
701
                                                        estate);
 
702
 
 
703
                /* Compute and save index expression values */
 
704
                exprvals = (Datum *) palloc(numrows * attr_cnt * sizeof(Datum));
 
705
                exprnulls = (bool *) palloc(numrows * attr_cnt * sizeof(bool));
 
706
                numindexrows = 0;
 
707
                tcnt = 0;
 
708
                for (rowno = 0; rowno < numrows; rowno++)
 
709
                {
 
710
                        HeapTuple       heapTuple = rows[rowno];
 
711
 
 
712
                        /*
 
713
                         * Reset the per-tuple context each time, to reclaim any cruft
 
714
                         * left behind by evaluating the predicate or index expressions.
 
715
                         */
 
716
                        ResetExprContext(econtext);
 
717
 
 
718
                        /* Set up for predicate or expression evaluation */
 
719
                        ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
 
720
 
 
721
                        /* If index is partial, check predicate */
 
722
                        if (predicate != NIL)
 
723
                        {
 
724
                                if (!ExecQual(predicate, econtext, false))
 
725
                                        continue;
 
726
                        }
 
727
                        numindexrows++;
 
728
 
 
729
                        if (attr_cnt > 0)
 
730
                        {
 
731
                                /*
 
732
                                 * Evaluate the index row to compute expression values. We
 
733
                                 * could do this by hand, but FormIndexDatum is convenient.
 
734
                                 */
 
735
                                FormIndexDatum(indexInfo,
 
736
                                                           slot,
 
737
                                                           estate,
 
738
                                                           values,
 
739
                                                           isnull);
 
740
 
 
741
                                /*
 
742
                                 * Save just the columns we care about.  We copy the values
 
743
                                 * into ind_context from the estate's per-tuple context.
 
744
                                 */
 
745
                                for (i = 0; i < attr_cnt; i++)
 
746
                                {
 
747
                                        VacAttrStats *stats = thisdata->vacattrstats[i];
 
748
                                        int                     attnum = stats->attr->attnum;
 
749
 
 
750
                                        if (isnull[attnum - 1])
 
751
                                        {
 
752
                                                exprvals[tcnt] = (Datum) 0;
 
753
                                                exprnulls[tcnt] = true;
 
754
                                        }
 
755
                                        else
 
756
                                        {
 
757
                                                exprvals[tcnt] = datumCopy(values[attnum - 1],
 
758
                                                                                                   stats->attrtype->typbyval,
 
759
                                                                                                   stats->attrtype->typlen);
 
760
                                                exprnulls[tcnt] = false;
 
761
                                        }
 
762
                                        tcnt++;
 
763
                                }
 
764
                        }
 
765
                }
 
766
 
 
767
                /*
 
768
                 * Having counted the number of rows that pass the predicate in the
 
769
                 * sample, we can estimate the total number of rows in the index.
 
770
                 */
 
771
                thisdata->tupleFract = (double) numindexrows / (double) numrows;
 
772
                totalindexrows = ceil(thisdata->tupleFract * totalrows);
 
773
 
 
774
                /*
 
775
                 * Now we can compute the statistics for the expression columns.
 
776
                 */
 
777
                if (numindexrows > 0)
 
778
                {
 
779
                        MemoryContextSwitchTo(col_context);
 
780
                        for (i = 0; i < attr_cnt; i++)
 
781
                        {
 
782
                                VacAttrStats *stats = thisdata->vacattrstats[i];
 
783
                                AttributeOpts *aopt =
 
784
                                get_attribute_options(stats->attr->attrelid,
 
785
                                                                          stats->attr->attnum);
 
786
 
 
787
                                stats->exprvals = exprvals + i;
 
788
                                stats->exprnulls = exprnulls + i;
 
789
                                stats->rowstride = attr_cnt;
 
790
                                (*stats->compute_stats) (stats,
 
791
                                                                                 ind_fetch_func,
 
792
                                                                                 numindexrows,
 
793
                                                                                 totalindexrows);
 
794
 
 
795
                                /*
 
796
                                 * If the n_distinct option is specified, it overrides the
 
797
                                 * above computation.  For indices, we always use just
 
798
                                 * n_distinct, not n_distinct_inherited.
 
799
                                 */
 
800
                                if (aopt != NULL && aopt->n_distinct != 0.0)
 
801
                                        stats->stadistinct = aopt->n_distinct;
 
802
 
 
803
                                MemoryContextResetAndDeleteChildren(col_context);
 
804
                        }
 
805
                }
 
806
 
 
807
                /* And clean up */
 
808
                MemoryContextSwitchTo(ind_context);
 
809
 
 
810
                ExecDropSingleTupleTableSlot(slot);
 
811
                FreeExecutorState(estate);
 
812
                MemoryContextResetAndDeleteChildren(ind_context);
 
813
        }
 
814
 
 
815
        MemoryContextSwitchTo(old_context);
 
816
        MemoryContextDelete(ind_context);
 
817
}
 
818
 
 
819
/*
 
820
 * examine_attribute -- pre-analysis of a single column
 
821
 *
 
822
 * Determine whether the column is analyzable; if so, create and initialize
 
823
 * a VacAttrStats struct for it.  If not, return NULL.
 
824
 *
 
825
 * If index_expr isn't NULL, then we're trying to analyze an expression index,
 
826
 * and index_expr is the expression tree representing the column's data.
 
827
 */
 
828
static VacAttrStats *
 
829
examine_attribute(Relation onerel, int attnum, Node *index_expr)
 
830
{
 
831
        Form_pg_attribute attr = onerel->rd_att->attrs[attnum - 1];
 
832
        HeapTuple       typtuple;
 
833
        VacAttrStats *stats;
 
834
        int                     i;
 
835
        bool            ok;
 
836
 
 
837
        /* Never analyze dropped columns */
 
838
        if (attr->attisdropped)
 
839
                return NULL;
 
840
 
 
841
        /* Don't analyze column if user has specified not to */
 
842
        if (attr->attstattarget == 0)
 
843
                return NULL;
 
844
 
 
845
        /*
 
846
         * Create the VacAttrStats struct.      Note that we only have a copy of the
 
847
         * fixed fields of the pg_attribute tuple.
 
848
         */
 
849
        stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats));
 
850
        stats->attr = (Form_pg_attribute) palloc(ATTRIBUTE_FIXED_PART_SIZE);
 
851
        memcpy(stats->attr, attr, ATTRIBUTE_FIXED_PART_SIZE);
 
852
 
 
853
        /*
 
854
         * When analyzing an expression index, believe the expression tree's type
 
855
         * not the column datatype --- the latter might be the opckeytype storage
 
856
         * type of the opclass, which is not interesting for our purposes.      (Note:
 
857
         * if we did anything with non-expression index columns, we'd need to
 
858
         * figure out where to get the correct type info from, but for now that's
 
859
         * not a problem.)      It's not clear whether anyone will care about the
 
860
         * typmod, but we store that too just in case.
 
861
         */
 
862
        if (index_expr)
 
863
        {
 
864
                stats->attrtypid = exprType(index_expr);
 
865
                stats->attrtypmod = exprTypmod(index_expr);
 
866
        }
 
867
        else
 
868
        {
 
869
                stats->attrtypid = attr->atttypid;
 
870
                stats->attrtypmod = attr->atttypmod;
 
871
        }
 
872
 
 
873
        typtuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(stats->attrtypid));
 
874
        if (!HeapTupleIsValid(typtuple))
 
875
                elog(ERROR, "cache lookup failed for type %u", stats->attrtypid);
 
876
        stats->attrtype = (Form_pg_type) palloc(sizeof(FormData_pg_type));
 
877
        memcpy(stats->attrtype, GETSTRUCT(typtuple), sizeof(FormData_pg_type));
 
878
        ReleaseSysCache(typtuple);
 
879
        stats->anl_context = anl_context;
 
880
        stats->tupattnum = attnum;
 
881
 
 
882
        /*
 
883
         * The fields describing the stats->stavalues[n] element types default to
 
884
         * the type of the data being analyzed, but the type-specific typanalyze
 
885
         * function can change them if it wants to store something else.
 
886
         */
 
887
        for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
 
888
        {
 
889
                stats->statypid[i] = stats->attrtypid;
 
890
                stats->statyplen[i] = stats->attrtype->typlen;
 
891
                stats->statypbyval[i] = stats->attrtype->typbyval;
 
892
                stats->statypalign[i] = stats->attrtype->typalign;
 
893
        }
 
894
 
 
895
        /*
 
896
         * Call the type-specific typanalyze function.  If none is specified, use
 
897
         * std_typanalyze().
 
898
         */
 
899
        if (OidIsValid(stats->attrtype->typanalyze))
 
900
                ok = DatumGetBool(OidFunctionCall1(stats->attrtype->typanalyze,
 
901
                                                                                   PointerGetDatum(stats)));
 
902
        else
 
903
                ok = std_typanalyze(stats);
 
904
 
 
905
        if (!ok || stats->compute_stats == NULL || stats->minrows <= 0)
 
906
        {
 
907
                pfree(stats->attrtype);
 
908
                pfree(stats->attr);
 
909
                pfree(stats);
 
910
                return NULL;
 
911
        }
 
912
 
 
913
        return stats;
 
914
}
 
915
 
 
916
/*
 
917
 * BlockSampler_Init -- prepare for random sampling of blocknumbers
 
918
 *
 
919
 * BlockSampler is used for stage one of our new two-stage tuple
 
920
 * sampling mechanism as discussed on pgsql-hackers 2004-04-02 (subject
 
921
 * "Large DB").  It selects a random sample of samplesize blocks out of
 
922
 * the nblocks blocks in the table.  If the table has less than
 
923
 * samplesize blocks, all blocks are selected.
 
924
 *
 
925
 * Since we know the total number of blocks in advance, we can use the
 
926
 * straightforward Algorithm S from Knuth 3.4.2, rather than Vitter's
 
927
 * algorithm.
 
928
 */
 
929
static void
 
930
BlockSampler_Init(BlockSampler bs, BlockNumber nblocks, int samplesize)
 
931
{
 
932
        bs->N = nblocks;                        /* measured table size */
 
933
 
 
934
        /*
 
935
         * If we decide to reduce samplesize for tables that have less or not much
 
936
         * more than samplesize blocks, here is the place to do it.
 
937
         */
 
938
        bs->n = samplesize;
 
939
        bs->t = 0;                                      /* blocks scanned so far */
 
940
        bs->m = 0;                                      /* blocks selected so far */
 
941
}
 
942
 
 
943
static bool
 
944
BlockSampler_HasMore(BlockSampler bs)
 
945
{
 
946
        return (bs->t < bs->N) && (bs->m < bs->n);
 
947
}
 
948
 
 
949
static BlockNumber
 
950
BlockSampler_Next(BlockSampler bs)
 
951
{
 
952
        BlockNumber K = bs->N - bs->t;          /* remaining blocks */
 
953
        int                     k = bs->n - bs->m;              /* blocks still to sample */
 
954
        double          p;                              /* probability to skip block */
 
955
        double          V;                              /* random */
 
956
 
 
957
        Assert(BlockSampler_HasMore(bs));       /* hence K > 0 and k > 0 */
 
958
 
 
959
        if ((BlockNumber) k >= K)
 
960
        {
 
961
                /* need all the rest */
 
962
                bs->m++;
 
963
                return bs->t++;
 
964
        }
 
965
 
 
966
        /*----------
 
967
         * It is not obvious that this code matches Knuth's Algorithm S.
 
968
         * Knuth says to skip the current block with probability 1 - k/K.
 
969
         * If we are to skip, we should advance t (hence decrease K), and
 
970
         * repeat the same probabilistic test for the next block.  The naive
 
971
         * implementation thus requires a random_fract() call for each block
 
972
         * number.      But we can reduce this to one random_fract() call per
 
973
         * selected block, by noting that each time the while-test succeeds,
 
974
         * we can reinterpret V as a uniform random number in the range 0 to p.
 
975
         * Therefore, instead of choosing a new V, we just adjust p to be
 
976
         * the appropriate fraction of its former value, and our next loop
 
977
         * makes the appropriate probabilistic test.
 
978
         *
 
979
         * We have initially K > k > 0.  If the loop reduces K to equal k,
 
980
         * the next while-test must fail since p will become exactly zero
 
981
         * (we assume there will not be roundoff error in the division).
 
982
         * (Note: Knuth suggests a "<=" loop condition, but we use "<" just
 
983
         * to be doubly sure about roundoff error.)  Therefore K cannot become
 
984
         * less than k, which means that we cannot fail to select enough blocks.
 
985
         *----------
 
986
         */
 
987
        V = random_fract();
 
988
        p = 1.0 - (double) k / (double) K;
 
989
        while (V < p)
 
990
        {
 
991
                /* skip */
 
992
                bs->t++;
 
993
                K--;                                    /* keep K == N - t */
 
994
 
 
995
                /* adjust p to be new cutoff point in reduced range */
 
996
                p *= 1.0 - (double) k / (double) K;
 
997
        }
 
998
 
 
999
        /* select */
 
1000
        bs->m++;
 
1001
        return bs->t++;
 
1002
}
 
1003
 
 
1004
/*
 
1005
 * acquire_sample_rows -- acquire a random sample of rows from the table
 
1006
 *
 
1007
 * Selected rows are returned in the caller-allocated array rows[], which
 
1008
 * must have at least targrows entries.
 
1009
 * The actual number of rows selected is returned as the function result.
 
1010
 * We also estimate the total numbers of live and dead rows in the table,
 
1011
 * and return them into *totalrows and *totaldeadrows, respectively.
 
1012
 *
 
1013
 * The returned list of tuples is in order by physical position in the table.
 
1014
 * (We will rely on this later to derive correlation estimates.)
 
1015
 *
 
1016
 * As of May 2004 we use a new two-stage method:  Stage one selects up
 
1017
 * to targrows random blocks (or all blocks, if there aren't so many).
 
1018
 * Stage two scans these blocks and uses the Vitter algorithm to create
 
1019
 * a random sample of targrows rows (or less, if there are less in the
 
1020
 * sample of blocks).  The two stages are executed simultaneously: each
 
1021
 * block is processed as soon as stage one returns its number and while
 
1022
 * the rows are read stage two controls which ones are to be inserted
 
1023
 * into the sample.
 
1024
 *
 
1025
 * Although every row has an equal chance of ending up in the final
 
1026
 * sample, this sampling method is not perfect: not every possible
 
1027
 * sample has an equal chance of being selected.  For large relations
 
1028
 * the number of different blocks represented by the sample tends to be
 
1029
 * too small.  We can live with that for now.  Improvements are welcome.
 
1030
 *
 
1031
 * An important property of this sampling method is that because we do
 
1032
 * look at a statistically unbiased set of blocks, we should get
 
1033
 * unbiased estimates of the average numbers of live and dead rows per
 
1034
 * block.  The previous sampling method put too much credence in the row
 
1035
 * density near the start of the table.
 
1036
 */
 
1037
static int
 
1038
acquire_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
 
1039
                                        double *totalrows, double *totaldeadrows)
 
1040
{
 
1041
        int                     numrows = 0;    /* # rows now in reservoir */
 
1042
        double          samplerows = 0; /* total # rows collected */
 
1043
        double          liverows = 0;   /* # live rows seen */
 
1044
        double          deadrows = 0;   /* # dead rows seen */
 
1045
        double          rowstoskip = -1;        /* -1 means not set yet */
 
1046
        BlockNumber totalblocks;
 
1047
        TransactionId OldestXmin;
 
1048
        BlockSamplerData bs;
 
1049
        double          rstate;
 
1050
 
 
1051
        Assert(targrows > 0);
 
1052
 
 
1053
        totalblocks = RelationGetNumberOfBlocks(onerel);
 
1054
 
 
1055
        /* Need a cutoff xmin for HeapTupleSatisfiesVacuum */
 
1056
        OldestXmin = GetOldestXmin(onerel->rd_rel->relisshared, true);
 
1057
 
 
1058
        /* Prepare for sampling block numbers */
 
1059
        BlockSampler_Init(&bs, totalblocks, targrows);
 
1060
        /* Prepare for sampling rows */
 
1061
        rstate = init_selection_state(targrows);
 
1062
 
 
1063
        /* Outer loop over blocks to sample */
 
1064
        while (BlockSampler_HasMore(&bs))
 
1065
        {
 
1066
                BlockNumber targblock = BlockSampler_Next(&bs);
 
1067
                Buffer          targbuffer;
 
1068
                Page            targpage;
 
1069
                OffsetNumber targoffset,
 
1070
                                        maxoffset;
 
1071
 
 
1072
                vacuum_delay_point();
 
1073
 
 
1074
                /*
 
1075
                 * We must maintain a pin on the target page's buffer to ensure that
 
1076
                 * the maxoffset value stays good (else concurrent VACUUM might delete
 
1077
                 * tuples out from under us).  Hence, pin the page until we are done
 
1078
                 * looking at it.  We also choose to hold sharelock on the buffer
 
1079
                 * throughout --- we could release and re-acquire sharelock for each
 
1080
                 * tuple, but since we aren't doing much work per tuple, the extra
 
1081
                 * lock traffic is probably better avoided.
 
1082
                 */
 
1083
                targbuffer = ReadBufferExtended(onerel, MAIN_FORKNUM, targblock,
 
1084
                                                                                RBM_NORMAL, vac_strategy);
 
1085
                LockBuffer(targbuffer, BUFFER_LOCK_SHARE);
 
1086
                targpage = BufferGetPage(targbuffer);
 
1087
                maxoffset = PageGetMaxOffsetNumber(targpage);
 
1088
 
 
1089
                /* Inner loop over all tuples on the selected page */
 
1090
                for (targoffset = FirstOffsetNumber; targoffset <= maxoffset; targoffset++)
 
1091
                {
 
1092
                        ItemId          itemid;
 
1093
                        HeapTupleData targtuple;
 
1094
                        bool            sample_it = false;
 
1095
 
 
1096
                        itemid = PageGetItemId(targpage, targoffset);
 
1097
 
 
1098
                        /*
 
1099
                         * We ignore unused and redirect line pointers.  DEAD line
 
1100
                         * pointers should be counted as dead, because we need vacuum to
 
1101
                         * run to get rid of them.      Note that this rule agrees with the
 
1102
                         * way that heap_page_prune() counts things.
 
1103
                         */
 
1104
                        if (!ItemIdIsNormal(itemid))
 
1105
                        {
 
1106
                                if (ItemIdIsDead(itemid))
 
1107
                                        deadrows += 1;
 
1108
                                continue;
 
1109
                        }
 
1110
 
 
1111
                        ItemPointerSet(&targtuple.t_self, targblock, targoffset);
 
1112
 
 
1113
                        targtuple.t_data = (HeapTupleHeader) PageGetItem(targpage, itemid);
 
1114
                        targtuple.t_len = ItemIdGetLength(itemid);
 
1115
 
 
1116
                        switch (HeapTupleSatisfiesVacuum(targtuple.t_data,
 
1117
                                                                                         OldestXmin,
 
1118
                                                                                         targbuffer))
 
1119
                        {
 
1120
                                case HEAPTUPLE_LIVE:
 
1121
                                        sample_it = true;
 
1122
                                        liverows += 1;
 
1123
                                        break;
 
1124
 
 
1125
                                case HEAPTUPLE_DEAD:
 
1126
                                case HEAPTUPLE_RECENTLY_DEAD:
 
1127
                                        /* Count dead and recently-dead rows */
 
1128
                                        deadrows += 1;
 
1129
                                        break;
 
1130
 
 
1131
                                case HEAPTUPLE_INSERT_IN_PROGRESS:
 
1132
 
 
1133
                                        /*
 
1134
                                         * Insert-in-progress rows are not counted.  We assume
 
1135
                                         * that when the inserting transaction commits or aborts,
 
1136
                                         * it will send a stats message to increment the proper
 
1137
                                         * count.  This works right only if that transaction ends
 
1138
                                         * after we finish analyzing the table; if things happen
 
1139
                                         * in the other order, its stats update will be
 
1140
                                         * overwritten by ours.  However, the error will be large
 
1141
                                         * only if the other transaction runs long enough to
 
1142
                                         * insert many tuples, so assuming it will finish after us
 
1143
                                         * is the safer option.
 
1144
                                         *
 
1145
                                         * A special case is that the inserting transaction might
 
1146
                                         * be our own.  In this case we should count and sample
 
1147
                                         * the row, to accommodate users who load a table and
 
1148
                                         * analyze it in one transaction.  (pgstat_report_analyze
 
1149
                                         * has to adjust the numbers we send to the stats
 
1150
                                         * collector to make this come out right.)
 
1151
                                         */
 
1152
                                        if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(targtuple.t_data)))
 
1153
                                        {
 
1154
                                                sample_it = true;
 
1155
                                                liverows += 1;
 
1156
                                        }
 
1157
                                        break;
 
1158
 
 
1159
                                case HEAPTUPLE_DELETE_IN_PROGRESS:
 
1160
 
 
1161
                                        /*
 
1162
                                         * We count delete-in-progress rows as still live, using
 
1163
                                         * the same reasoning given above; but we don't bother to
 
1164
                                         * include them in the sample.
 
1165
                                         *
 
1166
                                         * If the delete was done by our own transaction, however,
 
1167
                                         * we must count the row as dead to make
 
1168
                                         * pgstat_report_analyze's stats adjustments come out
 
1169
                                         * right.  (Note: this works out properly when the row was
 
1170
                                         * both inserted and deleted in our xact.)
 
1171
                                         */
 
1172
                                        if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(targtuple.t_data)))
 
1173
                                                deadrows += 1;
 
1174
                                        else
 
1175
                                                liverows += 1;
 
1176
                                        break;
 
1177
 
 
1178
                                default:
 
1179
                                        elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");
 
1180
                                        break;
 
1181
                        }
 
1182
 
 
1183
                        if (sample_it)
 
1184
                        {
 
1185
                                /*
 
1186
                                 * The first targrows sample rows are simply copied into the
 
1187
                                 * reservoir. Then we start replacing tuples in the sample
 
1188
                                 * until we reach the end of the relation.      This algorithm is
 
1189
                                 * from Jeff Vitter's paper (see full citation below). It
 
1190
                                 * works by repeatedly computing the number of tuples to skip
 
1191
                                 * before selecting a tuple, which replaces a randomly chosen
 
1192
                                 * element of the reservoir (current set of tuples).  At all
 
1193
                                 * times the reservoir is a true random sample of the tuples
 
1194
                                 * we've passed over so far, so when we fall off the end of
 
1195
                                 * the relation we're done.
 
1196
                                 */
 
1197
                                if (numrows < targrows)
 
1198
                                        rows[numrows++] = heap_copytuple(&targtuple);
 
1199
                                else
 
1200
                                {
 
1201
                                        /*
 
1202
                                         * t in Vitter's paper is the number of records already
 
1203
                                         * processed.  If we need to compute a new S value, we
 
1204
                                         * must use the not-yet-incremented value of samplerows as
 
1205
                                         * t.
 
1206
                                         */
 
1207
                                        if (rowstoskip < 0)
 
1208
                                                rowstoskip = get_next_S(samplerows, targrows, &rstate);
 
1209
 
 
1210
                                        if (rowstoskip <= 0)
 
1211
                                        {
 
1212
                                                /*
 
1213
                                                 * Found a suitable tuple, so save it, replacing one
 
1214
                                                 * old tuple at random
 
1215
                                                 */
 
1216
                                                int                     k = (int) (targrows * random_fract());
 
1217
 
 
1218
                                                Assert(k >= 0 && k < targrows);
 
1219
                                                heap_freetuple(rows[k]);
 
1220
                                                rows[k] = heap_copytuple(&targtuple);
 
1221
                                        }
 
1222
 
 
1223
                                        rowstoskip -= 1;
 
1224
                                }
 
1225
 
 
1226
                                samplerows += 1;
 
1227
                        }
 
1228
                }
 
1229
 
 
1230
                /* Now release the lock and pin on the page */
 
1231
                UnlockReleaseBuffer(targbuffer);
 
1232
        }
 
1233
 
 
1234
        /*
 
1235
         * If we didn't find as many tuples as we wanted then we're done. No sort
 
1236
         * is needed, since they're already in order.
 
1237
         *
 
1238
         * Otherwise we need to sort the collected tuples by position
 
1239
         * (itempointer). It's not worth worrying about corner cases where the
 
1240
         * tuples are already sorted.
 
1241
         */
 
1242
        if (numrows == targrows)
 
1243
                qsort((void *) rows, numrows, sizeof(HeapTuple), compare_rows);
 
1244
 
 
1245
        /*
 
1246
         * Estimate total numbers of rows in relation.
 
1247
         */
 
1248
        if (bs.m > 0)
 
1249
        {
 
1250
                *totalrows = floor((liverows * totalblocks) / bs.m + 0.5);
 
1251
                *totaldeadrows = floor((deadrows * totalblocks) / bs.m + 0.5);
 
1252
        }
 
1253
        else
 
1254
        {
 
1255
                *totalrows = 0.0;
 
1256
                *totaldeadrows = 0.0;
 
1257
        }
 
1258
 
 
1259
        /*
 
1260
         * Emit some interesting relation info
 
1261
         */
 
1262
        ereport(elevel,
 
1263
                        (errmsg("\"%s\": scanned %d of %u pages, "
 
1264
                                        "containing %.0f live rows and %.0f dead rows; "
 
1265
                                        "%d rows in sample, %.0f estimated total rows",
 
1266
                                        RelationGetRelationName(onerel),
 
1267
                                        bs.m, totalblocks,
 
1268
                                        liverows, deadrows,
 
1269
                                        numrows, *totalrows)));
 
1270
 
 
1271
        return numrows;
 
1272
}
 
1273
 
 
1274
/* Select a random value R uniformly distributed in (0 - 1) */
 
1275
static double
 
1276
random_fract(void)
 
1277
{
 
1278
        return ((double) random() + 1) / ((double) MAX_RANDOM_VALUE + 2);
 
1279
}
 
1280
 
 
1281
/*
 
1282
 * These two routines embody Algorithm Z from "Random sampling with a
 
1283
 * reservoir" by Jeffrey S. Vitter, in ACM Trans. Math. Softw. 11, 1
 
1284
 * (Mar. 1985), Pages 37-57.  Vitter describes his algorithm in terms
 
1285
 * of the count S of records to skip before processing another record.
 
1286
 * It is computed primarily based on t, the number of records already read.
 
1287
 * The only extra state needed between calls is W, a random state variable.
 
1288
 *
 
1289
 * init_selection_state computes the initial W value.
 
1290
 *
 
1291
 * Given that we've already read t records (t >= n), get_next_S
 
1292
 * determines the number of records to skip before the next record is
 
1293
 * processed.
 
1294
 */
 
1295
static double
 
1296
init_selection_state(int n)
 
1297
{
 
1298
        /* Initial value of W (for use when Algorithm Z is first applied) */
 
1299
        return exp(-log(random_fract()) / n);
 
1300
}
 
1301
 
 
1302
static double
 
1303
get_next_S(double t, int n, double *stateptr)
 
1304
{
 
1305
        double          S;
 
1306
 
 
1307
        /* The magic constant here is T from Vitter's paper */
 
1308
        if (t <= (22.0 * n))
 
1309
        {
 
1310
                /* Process records using Algorithm X until t is large enough */
 
1311
                double          V,
 
1312
                                        quot;
 
1313
 
 
1314
                V = random_fract();             /* Generate V */
 
1315
                S = 0;
 
1316
                t += 1;
 
1317
                /* Note: "num" in Vitter's code is always equal to t - n */
 
1318
                quot = (t - (double) n) / t;
 
1319
                /* Find min S satisfying (4.1) */
 
1320
                while (quot > V)
 
1321
                {
 
1322
                        S += 1;
 
1323
                        t += 1;
 
1324
                        quot *= (t - (double) n) / t;
 
1325
                }
 
1326
        }
 
1327
        else
 
1328
        {
 
1329
                /* Now apply Algorithm Z */
 
1330
                double          W = *stateptr;
 
1331
                double          term = t - (double) n + 1;
 
1332
 
 
1333
                for (;;)
 
1334
                {
 
1335
                        double          numer,
 
1336
                                                numer_lim,
 
1337
                                                denom;
 
1338
                        double          U,
 
1339
                                                X,
 
1340
                                                lhs,
 
1341
                                                rhs,
 
1342
                                                y,
 
1343
                                                tmp;
 
1344
 
 
1345
                        /* Generate U and X */
 
1346
                        U = random_fract();
 
1347
                        X = t * (W - 1.0);
 
1348
                        S = floor(X);           /* S is tentatively set to floor(X) */
 
1349
                        /* Test if U <= h(S)/cg(X) in the manner of (6.3) */
 
1350
                        tmp = (t + 1) / term;
 
1351
                        lhs = exp(log(((U * tmp * tmp) * (term + S)) / (t + X)) / n);
 
1352
                        rhs = (((t + X) / (term + S)) * term) / t;
 
1353
                        if (lhs <= rhs)
 
1354
                        {
 
1355
                                W = rhs / lhs;
 
1356
                                break;
 
1357
                        }
 
1358
                        /* Test if U <= f(S)/cg(X) */
 
1359
                        y = (((U * (t + 1)) / term) * (t + S + 1)) / (t + X);
 
1360
                        if ((double) n < S)
 
1361
                        {
 
1362
                                denom = t;
 
1363
                                numer_lim = term + S;
 
1364
                        }
 
1365
                        else
 
1366
                        {
 
1367
                                denom = t - (double) n + S;
 
1368
                                numer_lim = t + 1;
 
1369
                        }
 
1370
                        for (numer = t + S; numer >= numer_lim; numer -= 1)
 
1371
                        {
 
1372
                                y *= numer / denom;
 
1373
                                denom -= 1;
 
1374
                        }
 
1375
                        W = exp(-log(random_fract()) / n);      /* Generate W in advance */
 
1376
                        if (exp(log(y) / n) <= (t + X) / t)
 
1377
                                break;
 
1378
                }
 
1379
                *stateptr = W;
 
1380
        }
 
1381
        return S;
 
1382
}
 
1383
 
 
1384
/*
 
1385
 * qsort comparator for sorting rows[] array
 
1386
 */
 
1387
static int
 
1388
compare_rows(const void *a, const void *b)
 
1389
{
 
1390
        HeapTuple       ha = *(HeapTuple *) a;
 
1391
        HeapTuple       hb = *(HeapTuple *) b;
 
1392
        BlockNumber ba = ItemPointerGetBlockNumber(&ha->t_self);
 
1393
        OffsetNumber oa = ItemPointerGetOffsetNumber(&ha->t_self);
 
1394
        BlockNumber bb = ItemPointerGetBlockNumber(&hb->t_self);
 
1395
        OffsetNumber ob = ItemPointerGetOffsetNumber(&hb->t_self);
 
1396
 
 
1397
        if (ba < bb)
 
1398
                return -1;
 
1399
        if (ba > bb)
 
1400
                return 1;
 
1401
        if (oa < ob)
 
1402
                return -1;
 
1403
        if (oa > ob)
 
1404
                return 1;
 
1405
        return 0;
 
1406
}
 
1407
 
 
1408
 
 
1409
/*
 
1410
 * acquire_inherited_sample_rows -- acquire sample rows from inheritance tree
 
1411
 *
 
1412
 * This has the same API as acquire_sample_rows, except that rows are
 
1413
 * collected from all inheritance children as well as the specified table.
 
1414
 * We fail and return zero if there are no inheritance children.
 
1415
 */
 
1416
static int
 
1417
acquire_inherited_sample_rows(Relation onerel, HeapTuple *rows, int targrows,
 
1418
                                                          double *totalrows, double *totaldeadrows)
 
1419
{
 
1420
        List       *tableOIDs;
 
1421
        Relation   *rels;
 
1422
        double     *relblocks;
 
1423
        double          totalblocks;
 
1424
        int                     numrows,
 
1425
                                nrels,
 
1426
                                i;
 
1427
        ListCell   *lc;
 
1428
 
 
1429
        /*
 
1430
         * Find all members of inheritance set.  We only need AccessShareLock on
 
1431
         * the children.
 
1432
         */
 
1433
        tableOIDs =
 
1434
                find_all_inheritors(RelationGetRelid(onerel), AccessShareLock, NULL);
 
1435
 
 
1436
        /*
 
1437
         * Check that there's at least one descendant, else fail.  This could
 
1438
         * happen despite analyze_rel's relhassubclass check, if table once had a
 
1439
         * child but no longer does.
 
1440
         */
 
1441
        if (list_length(tableOIDs) < 2)
 
1442
        {
 
1443
                /*
 
1444
                 * XXX It would be desirable to clear relhassubclass here, but we
 
1445
                 * don't have adequate lock to do that safely.
 
1446
                 */
 
1447
                return 0;
 
1448
        }
 
1449
 
 
1450
        /*
 
1451
         * Count the blocks in all the relations.  The result could overflow
 
1452
         * BlockNumber, so we use double arithmetic.
 
1453
         */
 
1454
        rels = (Relation *) palloc(list_length(tableOIDs) * sizeof(Relation));
 
1455
        relblocks = (double *) palloc(list_length(tableOIDs) * sizeof(double));
 
1456
        totalblocks = 0;
 
1457
        nrels = 0;
 
1458
        foreach(lc, tableOIDs)
 
1459
        {
 
1460
                Oid                     childOID = lfirst_oid(lc);
 
1461
                Relation        childrel;
 
1462
 
 
1463
                /* We already got the needed lock */
 
1464
                childrel = heap_open(childOID, NoLock);
 
1465
 
 
1466
                /* Ignore if temp table of another backend */
 
1467
                if (RELATION_IS_OTHER_TEMP(childrel))
 
1468
                {
 
1469
                        /* ... but release the lock on it */
 
1470
                        Assert(childrel != onerel);
 
1471
                        heap_close(childrel, AccessShareLock);
 
1472
                        continue;
 
1473
                }
 
1474
 
 
1475
                rels[nrels] = childrel;
 
1476
                relblocks[nrels] = (double) RelationGetNumberOfBlocks(childrel);
 
1477
                totalblocks += relblocks[nrels];
 
1478
                nrels++;
 
1479
        }
 
1480
 
 
1481
        /*
 
1482
         * Now sample rows from each relation, proportionally to its fraction of
 
1483
         * the total block count.  (This might be less than desirable if the child
 
1484
         * rels have radically different free-space percentages, but it's not
 
1485
         * clear that it's worth working harder.)
 
1486
         */
 
1487
        numrows = 0;
 
1488
        *totalrows = 0;
 
1489
        *totaldeadrows = 0;
 
1490
        for (i = 0; i < nrels; i++)
 
1491
        {
 
1492
                Relation        childrel = rels[i];
 
1493
                double          childblocks = relblocks[i];
 
1494
 
 
1495
                if (childblocks > 0)
 
1496
                {
 
1497
                        int                     childtargrows;
 
1498
 
 
1499
                        childtargrows = (int) rint(targrows * childblocks / totalblocks);
 
1500
                        /* Make sure we don't overrun due to roundoff error */
 
1501
                        childtargrows = Min(childtargrows, targrows - numrows);
 
1502
                        if (childtargrows > 0)
 
1503
                        {
 
1504
                                int                     childrows;
 
1505
                                double          trows,
 
1506
                                                        tdrows;
 
1507
 
 
1508
                                /* Fetch a random sample of the child's rows */
 
1509
                                childrows = acquire_sample_rows(childrel,
 
1510
                                                                                                rows + numrows,
 
1511
                                                                                                childtargrows,
 
1512
                                                                                                &trows,
 
1513
                                                                                                &tdrows);
 
1514
 
 
1515
                                /* We may need to convert from child's rowtype to parent's */
 
1516
                                if (childrows > 0 &&
 
1517
                                        !equalTupleDescs(RelationGetDescr(childrel),
 
1518
                                                                         RelationGetDescr(onerel)))
 
1519
                                {
 
1520
                                        TupleConversionMap *map;
 
1521
 
 
1522
                                        map = convert_tuples_by_name(RelationGetDescr(childrel),
 
1523
                                                                                                 RelationGetDescr(onerel),
 
1524
                                                                 gettext_noop("could not convert row type"));
 
1525
                                        if (map != NULL)
 
1526
                                        {
 
1527
                                                int                     j;
 
1528
 
 
1529
                                                for (j = 0; j < childrows; j++)
 
1530
                                                {
 
1531
                                                        HeapTuple       newtup;
 
1532
 
 
1533
                                                        newtup = do_convert_tuple(rows[numrows + j], map);
 
1534
                                                        heap_freetuple(rows[numrows + j]);
 
1535
                                                        rows[numrows + j] = newtup;
 
1536
                                                }
 
1537
                                                free_conversion_map(map);
 
1538
                                        }
 
1539
                                }
 
1540
 
 
1541
                                /* And add to counts */
 
1542
                                numrows += childrows;
 
1543
                                *totalrows += trows;
 
1544
                                *totaldeadrows += tdrows;
 
1545
                        }
 
1546
                }
 
1547
 
 
1548
                /*
 
1549
                 * Note: we cannot release the child-table locks, since we may have
 
1550
                 * pointers to their TOAST tables in the sampled rows.
 
1551
                 */
 
1552
                heap_close(childrel, NoLock);
 
1553
        }
 
1554
 
 
1555
        return numrows;
 
1556
}
 
1557
 
 
1558
 
 
1559
/*
 
1560
 *      update_attstats() -- update attribute statistics for one relation
 
1561
 *
 
1562
 *              Statistics are stored in several places: the pg_class row for the
 
1563
 *              relation has stats about the whole relation, and there is a
 
1564
 *              pg_statistic row for each (non-system) attribute that has ever
 
1565
 *              been analyzed.  The pg_class values are updated by VACUUM, not here.
 
1566
 *
 
1567
 *              pg_statistic rows are just added or updated normally.  This means
 
1568
 *              that pg_statistic will probably contain some deleted rows at the
 
1569
 *              completion of a vacuum cycle, unless it happens to get vacuumed last.
 
1570
 *
 
1571
 *              To keep things simple, we punt for pg_statistic, and don't try
 
1572
 *              to compute or store rows for pg_statistic itself in pg_statistic.
 
1573
 *              This could possibly be made to work, but it's not worth the trouble.
 
1574
 *              Note analyze_rel() has seen to it that we won't come here when
 
1575
 *              vacuuming pg_statistic itself.
 
1576
 *
 
1577
 *              Note: there would be a race condition here if two backends could
 
1578
 *              ANALYZE the same table concurrently.  Presently, we lock that out
 
1579
 *              by taking a self-exclusive lock on the relation in analyze_rel().
 
1580
 */
 
1581
static void
 
1582
update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
 
1583
{
 
1584
        Relation        sd;
 
1585
        int                     attno;
 
1586
 
 
1587
        if (natts <= 0)
 
1588
                return;                                 /* nothing to do */
 
1589
 
 
1590
        sd = heap_open(StatisticRelationId, RowExclusiveLock);
 
1591
 
 
1592
        for (attno = 0; attno < natts; attno++)
 
1593
        {
 
1594
                VacAttrStats *stats = vacattrstats[attno];
 
1595
                HeapTuple       stup,
 
1596
                                        oldtup;
 
1597
                int                     i,
 
1598
                                        k,
 
1599
                                        n;
 
1600
                Datum           values[Natts_pg_statistic];
 
1601
                bool            nulls[Natts_pg_statistic];
 
1602
                bool            replaces[Natts_pg_statistic];
 
1603
 
 
1604
                /* Ignore attr if we weren't able to collect stats */
 
1605
                if (!stats->stats_valid)
 
1606
                        continue;
 
1607
 
 
1608
                /*
 
1609
                 * Construct a new pg_statistic tuple
 
1610
                 */
 
1611
                for (i = 0; i < Natts_pg_statistic; ++i)
 
1612
                {
 
1613
                        nulls[i] = false;
 
1614
                        replaces[i] = true;
 
1615
                }
 
1616
 
 
1617
                i = 0;
 
1618
                values[i++] = ObjectIdGetDatum(relid);  /* starelid */
 
1619
                values[i++] = Int16GetDatum(stats->attr->attnum);               /* staattnum */
 
1620
                values[i++] = BoolGetDatum(inh);                /* stainherit */
 
1621
                values[i++] = Float4GetDatum(stats->stanullfrac);               /* stanullfrac */
 
1622
                values[i++] = Int32GetDatum(stats->stawidth);   /* stawidth */
 
1623
                values[i++] = Float4GetDatum(stats->stadistinct);               /* stadistinct */
 
1624
                for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
 
1625
                {
 
1626
                        values[i++] = Int16GetDatum(stats->stakind[k]);         /* stakindN */
 
1627
                }
 
1628
                for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
 
1629
                {
 
1630
                        values[i++] = ObjectIdGetDatum(stats->staop[k]);        /* staopN */
 
1631
                }
 
1632
                for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
 
1633
                {
 
1634
                        int                     nnum = stats->numnumbers[k];
 
1635
 
 
1636
                        if (nnum > 0)
 
1637
                        {
 
1638
                                Datum      *numdatums = (Datum *) palloc(nnum * sizeof(Datum));
 
1639
                                ArrayType  *arry;
 
1640
 
 
1641
                                for (n = 0; n < nnum; n++)
 
1642
                                        numdatums[n] = Float4GetDatum(stats->stanumbers[k][n]);
 
1643
                                /* XXX knows more than it should about type float4: */
 
1644
                                arry = construct_array(numdatums, nnum,
 
1645
                                                                           FLOAT4OID,
 
1646
                                                                           sizeof(float4), FLOAT4PASSBYVAL, 'i');
 
1647
                                values[i++] = PointerGetDatum(arry);    /* stanumbersN */
 
1648
                        }
 
1649
                        else
 
1650
                        {
 
1651
                                nulls[i] = true;
 
1652
                                values[i++] = (Datum) 0;
 
1653
                        }
 
1654
                }
 
1655
                for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
 
1656
                {
 
1657
                        if (stats->numvalues[k] > 0)
 
1658
                        {
 
1659
                                ArrayType  *arry;
 
1660
 
 
1661
                                arry = construct_array(stats->stavalues[k],
 
1662
                                                                           stats->numvalues[k],
 
1663
                                                                           stats->statypid[k],
 
1664
                                                                           stats->statyplen[k],
 
1665
                                                                           stats->statypbyval[k],
 
1666
                                                                           stats->statypalign[k]);
 
1667
                                values[i++] = PointerGetDatum(arry);    /* stavaluesN */
 
1668
                        }
 
1669
                        else
 
1670
                        {
 
1671
                                nulls[i] = true;
 
1672
                                values[i++] = (Datum) 0;
 
1673
                        }
 
1674
                }
 
1675
 
 
1676
                /* Is there already a pg_statistic tuple for this attribute? */
 
1677
                oldtup = SearchSysCache3(STATRELATTINH,
 
1678
                                                                 ObjectIdGetDatum(relid),
 
1679
                                                                 Int16GetDatum(stats->attr->attnum),
 
1680
                                                                 BoolGetDatum(inh));
 
1681
 
 
1682
                if (HeapTupleIsValid(oldtup))
 
1683
                {
 
1684
                        /* Yes, replace it */
 
1685
                        stup = heap_modify_tuple(oldtup,
 
1686
                                                                         RelationGetDescr(sd),
 
1687
                                                                         values,
 
1688
                                                                         nulls,
 
1689
                                                                         replaces);
 
1690
                        ReleaseSysCache(oldtup);
 
1691
                        simple_heap_update(sd, &stup->t_self, stup);
 
1692
                }
 
1693
                else
 
1694
                {
 
1695
                        /* No, insert new tuple */
 
1696
                        stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
 
1697
                        simple_heap_insert(sd, stup);
 
1698
                }
 
1699
 
 
1700
                /* update indexes too */
 
1701
                CatalogUpdateIndexes(sd, stup);
 
1702
 
 
1703
                heap_freetuple(stup);
 
1704
        }
 
1705
 
 
1706
        heap_close(sd, RowExclusiveLock);
 
1707
}
 
1708
 
 
1709
/*
 
1710
 * Standard fetch function for use by compute_stats subroutines.
 
1711
 *
 
1712
 * This exists to provide some insulation between compute_stats routines
 
1713
 * and the actual storage of the sample data.
 
1714
 */
 
1715
static Datum
 
1716
std_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull)
 
1717
{
 
1718
        int                     attnum = stats->tupattnum;
 
1719
        HeapTuple       tuple = stats->rows[rownum];
 
1720
        TupleDesc       tupDesc = stats->tupDesc;
 
1721
 
 
1722
        return heap_getattr(tuple, attnum, tupDesc, isNull);
 
1723
}
 
1724
 
 
1725
/*
 
1726
 * Fetch function for analyzing index expressions.
 
1727
 *
 
1728
 * We have not bothered to construct index tuples, instead the data is
 
1729
 * just in Datum arrays.
 
1730
 */
 
1731
static Datum
 
1732
ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull)
 
1733
{
 
1734
        int                     i;
 
1735
 
 
1736
        /* exprvals and exprnulls are already offset for proper column */
 
1737
        i = rownum * stats->rowstride;
 
1738
        *isNull = stats->exprnulls[i];
 
1739
        return stats->exprvals[i];
 
1740
}
 
1741
 
 
1742
 
 
1743
/*==========================================================================
 
1744
 *
 
1745
 * Code below this point represents the "standard" type-specific statistics
 
1746
 * analysis algorithms.  This code can be replaced on a per-data-type basis
 
1747
 * by setting a nonzero value in pg_type.typanalyze.
 
1748
 *
 
1749
 *==========================================================================
 
1750
 */
 
1751
 
 
1752
 
 
1753
/*
 
1754
 * To avoid consuming too much memory during analysis and/or too much space
 
1755
 * in the resulting pg_statistic rows, we ignore varlena datums that are wider
 
1756
 * than WIDTH_THRESHOLD (after detoasting!).  This is legitimate for MCV
 
1757
 * and distinct-value calculations since a wide value is unlikely to be
 
1758
 * duplicated at all, much less be a most-common value.  For the same reason,
 
1759
 * ignoring wide values will not affect our estimates of histogram bin
 
1760
 * boundaries very much.
 
1761
 */
 
1762
#define WIDTH_THRESHOLD  1024
 
1763
 
 
1764
#define swapInt(a,b)    do {int _tmp; _tmp=a; a=b; b=_tmp;} while(0)
 
1765
#define swapDatum(a,b)  do {Datum _tmp; _tmp=a; a=b; b=_tmp;} while(0)
 
1766
 
 
1767
/*
 
1768
 * Extra information used by the default analysis routines
 
1769
 */
 
1770
typedef struct
 
1771
{
 
1772
        Oid                     eqopr;                  /* '=' operator for datatype, if any */
 
1773
        Oid                     eqfunc;                 /* and associated function */
 
1774
        Oid                     ltopr;                  /* '<' operator for datatype, if any */
 
1775
} StdAnalyzeData;
 
1776
 
 
1777
typedef struct
 
1778
{
 
1779
        Datum           value;                  /* a data value */
 
1780
        int                     tupno;                  /* position index for tuple it came from */
 
1781
} ScalarItem;
 
1782
 
 
1783
typedef struct
 
1784
{
 
1785
        int                     count;                  /* # of duplicates */
 
1786
        int                     first;                  /* values[] index of first occurrence */
 
1787
} ScalarMCVItem;
 
1788
 
 
1789
typedef struct
 
1790
{
 
1791
        FmgrInfo   *cmpFn;
 
1792
        int                     cmpFlags;
 
1793
        int                *tupnoLink;
 
1794
} CompareScalarsContext;
 
1795
 
 
1796
 
 
1797
static void compute_minimal_stats(VacAttrStatsP stats,
 
1798
                                          AnalyzeAttrFetchFunc fetchfunc,
 
1799
                                          int samplerows,
 
1800
                                          double totalrows);
 
1801
static void compute_scalar_stats(VacAttrStatsP stats,
 
1802
                                         AnalyzeAttrFetchFunc fetchfunc,
 
1803
                                         int samplerows,
 
1804
                                         double totalrows);
 
1805
static int      compare_scalars(const void *a, const void *b, void *arg);
 
1806
static int      compare_mcvs(const void *a, const void *b);
 
1807
 
 
1808
 
 
1809
/*
 
1810
 * std_typanalyze -- the default type-specific typanalyze function
 
1811
 */
 
1812
static bool
 
1813
std_typanalyze(VacAttrStats *stats)
 
1814
{
 
1815
        Form_pg_attribute attr = stats->attr;
 
1816
        Oid                     ltopr;
 
1817
        Oid                     eqopr;
 
1818
        StdAnalyzeData *mystats;
 
1819
 
 
1820
        /* If the attstattarget column is negative, use the default value */
 
1821
        /* NB: it is okay to scribble on stats->attr since it's a copy */
 
1822
        if (attr->attstattarget < 0)
 
1823
                attr->attstattarget = default_statistics_target;
 
1824
 
 
1825
        /* Look for default "<" and "=" operators for column's type */
 
1826
        get_sort_group_operators(stats->attrtypid,
 
1827
                                                         false, false, false,
 
1828
                                                         &ltopr, &eqopr, NULL,
 
1829
                                                         NULL);
 
1830
 
 
1831
        /* If column has no "=" operator, we can't do much of anything */
 
1832
        if (!OidIsValid(eqopr))
 
1833
                return false;
 
1834
 
 
1835
        /* Save the operator info for compute_stats routines */
 
1836
        mystats = (StdAnalyzeData *) palloc(sizeof(StdAnalyzeData));
 
1837
        mystats->eqopr = eqopr;
 
1838
        mystats->eqfunc = get_opcode(eqopr);
 
1839
        mystats->ltopr = ltopr;
 
1840
        stats->extra_data = mystats;
 
1841
 
 
1842
        /*
 
1843
         * Determine which standard statistics algorithm to use
 
1844
         */
 
1845
        if (OidIsValid(ltopr))
 
1846
        {
 
1847
                /* Seems to be a scalar datatype */
 
1848
                stats->compute_stats = compute_scalar_stats;
 
1849
                /*--------------------
 
1850
                 * The following choice of minrows is based on the paper
 
1851
                 * "Random sampling for histogram construction: how much is enough?"
 
1852
                 * by Surajit Chaudhuri, Rajeev Motwani and Vivek Narasayya, in
 
1853
                 * Proceedings of ACM SIGMOD International Conference on Management
 
1854
                 * of Data, 1998, Pages 436-447.  Their Corollary 1 to Theorem 5
 
1855
                 * says that for table size n, histogram size k, maximum relative
 
1856
                 * error in bin size f, and error probability gamma, the minimum
 
1857
                 * random sample size is
 
1858
                 *              r = 4 * k * ln(2*n/gamma) / f^2
 
1859
                 * Taking f = 0.5, gamma = 0.01, n = 10^6 rows, we obtain
 
1860
                 *              r = 305.82 * k
 
1861
                 * Note that because of the log function, the dependence on n is
 
1862
                 * quite weak; even at n = 10^12, a 300*k sample gives <= 0.66
 
1863
                 * bin size error with probability 0.99.  So there's no real need to
 
1864
                 * scale for n, which is a good thing because we don't necessarily
 
1865
                 * know it at this point.
 
1866
                 *--------------------
 
1867
                 */
 
1868
                stats->minrows = 300 * attr->attstattarget;
 
1869
        }
 
1870
        else
 
1871
        {
 
1872
                /* Can't do much but the minimal stuff */
 
1873
                stats->compute_stats = compute_minimal_stats;
 
1874
                /* Might as well use the same minrows as above */
 
1875
                stats->minrows = 300 * attr->attstattarget;
 
1876
        }
 
1877
 
 
1878
        return true;
 
1879
}
 
1880
 
 
1881
/*
 
1882
 *      compute_minimal_stats() -- compute minimal column statistics
 
1883
 *
 
1884
 *      We use this when we can find only an "=" operator for the datatype.
 
1885
 *
 
1886
 *      We determine the fraction of non-null rows, the average width, the
 
1887
 *      most common values, and the (estimated) number of distinct values.
 
1888
 *
 
1889
 *      The most common values are determined by brute force: we keep a list
 
1890
 *      of previously seen values, ordered by number of times seen, as we scan
 
1891
 *      the samples.  A newly seen value is inserted just after the last
 
1892
 *      multiply-seen value, causing the bottommost (oldest) singly-seen value
 
1893
 *      to drop off the list.  The accuracy of this method, and also its cost,
 
1894
 *      depend mainly on the length of the list we are willing to keep.
 
1895
 */
 
1896
static void
 
1897
compute_minimal_stats(VacAttrStatsP stats,
 
1898
                                          AnalyzeAttrFetchFunc fetchfunc,
 
1899
                                          int samplerows,
 
1900
                                          double totalrows)
 
1901
{
 
1902
        int                     i;
 
1903
        int                     null_cnt = 0;
 
1904
        int                     nonnull_cnt = 0;
 
1905
        int                     toowide_cnt = 0;
 
1906
        double          total_width = 0;
 
1907
        bool            is_varlena = (!stats->attrtype->typbyval &&
 
1908
                                                          stats->attrtype->typlen == -1);
 
1909
        bool            is_varwidth = (!stats->attrtype->typbyval &&
 
1910
                                                           stats->attrtype->typlen < 0);
 
1911
        FmgrInfo        f_cmpeq;
 
1912
        typedef struct
 
1913
        {
 
1914
                Datum           value;
 
1915
                int                     count;
 
1916
        } TrackItem;
 
1917
        TrackItem  *track;
 
1918
        int                     track_cnt,
 
1919
                                track_max;
 
1920
        int                     num_mcv = stats->attr->attstattarget;
 
1921
        StdAnalyzeData *mystats = (StdAnalyzeData *) stats->extra_data;
 
1922
 
 
1923
        /*
 
1924
         * We track up to 2*n values for an n-element MCV list; but at least 10
 
1925
         */
 
1926
        track_max = 2 * num_mcv;
 
1927
        if (track_max < 10)
 
1928
                track_max = 10;
 
1929
        track = (TrackItem *) palloc(track_max * sizeof(TrackItem));
 
1930
        track_cnt = 0;
 
1931
 
 
1932
        fmgr_info(mystats->eqfunc, &f_cmpeq);
 
1933
 
 
1934
        for (i = 0; i < samplerows; i++)
 
1935
        {
 
1936
                Datum           value;
 
1937
                bool            isnull;
 
1938
                bool            match;
 
1939
                int                     firstcount1,
 
1940
                                        j;
 
1941
 
 
1942
                vacuum_delay_point();
 
1943
 
 
1944
                value = fetchfunc(stats, i, &isnull);
 
1945
 
 
1946
                /* Check for null/nonnull */
 
1947
                if (isnull)
 
1948
                {
 
1949
                        null_cnt++;
 
1950
                        continue;
 
1951
                }
 
1952
                nonnull_cnt++;
 
1953
 
 
1954
                /*
 
1955
                 * If it's a variable-width field, add up widths for average width
 
1956
                 * calculation.  Note that if the value is toasted, we use the toasted
 
1957
                 * width.  We don't bother with this calculation if it's a fixed-width
 
1958
                 * type.
 
1959
                 */
 
1960
                if (is_varlena)
 
1961
                {
 
1962
                        total_width += VARSIZE_ANY(DatumGetPointer(value));
 
1963
 
 
1964
                        /*
 
1965
                         * If the value is toasted, we want to detoast it just once to
 
1966
                         * avoid repeated detoastings and resultant excess memory usage
 
1967
                         * during the comparisons.      Also, check to see if the value is
 
1968
                         * excessively wide, and if so don't detoast at all --- just
 
1969
                         * ignore the value.
 
1970
                         */
 
1971
                        if (toast_raw_datum_size(value) > WIDTH_THRESHOLD)
 
1972
                        {
 
1973
                                toowide_cnt++;
 
1974
                                continue;
 
1975
                        }
 
1976
                        value = PointerGetDatum(PG_DETOAST_DATUM(value));
 
1977
                }
 
1978
                else if (is_varwidth)
 
1979
                {
 
1980
                        /* must be cstring */
 
1981
                        total_width += strlen(DatumGetCString(value)) + 1;
 
1982
                }
 
1983
 
 
1984
                /*
 
1985
                 * See if the value matches anything we're already tracking.
 
1986
                 */
 
1987
                match = false;
 
1988
                firstcount1 = track_cnt;
 
1989
                for (j = 0; j < track_cnt; j++)
 
1990
                {
 
1991
                        /* We always use the default collation for statistics */
 
1992
                        if (DatumGetBool(FunctionCall2Coll(&f_cmpeq,
 
1993
                                                                                           DEFAULT_COLLATION_OID,
 
1994
                                                                                           value, track[j].value)))
 
1995
                        {
 
1996
                                match = true;
 
1997
                                break;
 
1998
                        }
 
1999
                        if (j < firstcount1 && track[j].count == 1)
 
2000
                                firstcount1 = j;
 
2001
                }
 
2002
 
 
2003
                if (match)
 
2004
                {
 
2005
                        /* Found a match */
 
2006
                        track[j].count++;
 
2007
                        /* This value may now need to "bubble up" in the track list */
 
2008
                        while (j > 0 && track[j].count > track[j - 1].count)
 
2009
                        {
 
2010
                                swapDatum(track[j].value, track[j - 1].value);
 
2011
                                swapInt(track[j].count, track[j - 1].count);
 
2012
                                j--;
 
2013
                        }
 
2014
                }
 
2015
                else
 
2016
                {
 
2017
                        /* No match.  Insert at head of count-1 list */
 
2018
                        if (track_cnt < track_max)
 
2019
                                track_cnt++;
 
2020
                        for (j = track_cnt - 1; j > firstcount1; j--)
 
2021
                        {
 
2022
                                track[j].value = track[j - 1].value;
 
2023
                                track[j].count = track[j - 1].count;
 
2024
                        }
 
2025
                        if (firstcount1 < track_cnt)
 
2026
                        {
 
2027
                                track[firstcount1].value = value;
 
2028
                                track[firstcount1].count = 1;
 
2029
                        }
 
2030
                }
 
2031
        }
 
2032
 
 
2033
        /* We can only compute real stats if we found some non-null values. */
 
2034
        if (nonnull_cnt > 0)
 
2035
        {
 
2036
                int                     nmultiple,
 
2037
                                        summultiple;
 
2038
 
 
2039
                stats->stats_valid = true;
 
2040
                /* Do the simple null-frac and width stats */
 
2041
                stats->stanullfrac = (double) null_cnt / (double) samplerows;
 
2042
                if (is_varwidth)
 
2043
                        stats->stawidth = total_width / (double) nonnull_cnt;
 
2044
                else
 
2045
                        stats->stawidth = stats->attrtype->typlen;
 
2046
 
 
2047
                /* Count the number of values we found multiple times */
 
2048
                summultiple = 0;
 
2049
                for (nmultiple = 0; nmultiple < track_cnt; nmultiple++)
 
2050
                {
 
2051
                        if (track[nmultiple].count == 1)
 
2052
                                break;
 
2053
                        summultiple += track[nmultiple].count;
 
2054
                }
 
2055
 
 
2056
                if (nmultiple == 0)
 
2057
                {
 
2058
                        /* If we found no repeated values, assume it's a unique column */
 
2059
                        stats->stadistinct = -1.0;
 
2060
                }
 
2061
                else if (track_cnt < track_max && toowide_cnt == 0 &&
 
2062
                                 nmultiple == track_cnt)
 
2063
                {
 
2064
                        /*
 
2065
                         * Our track list includes every value in the sample, and every
 
2066
                         * value appeared more than once.  Assume the column has just
 
2067
                         * these values.
 
2068
                         */
 
2069
                        stats->stadistinct = track_cnt;
 
2070
                }
 
2071
                else
 
2072
                {
 
2073
                        /*----------
 
2074
                         * Estimate the number of distinct values using the estimator
 
2075
                         * proposed by Haas and Stokes in IBM Research Report RJ 10025:
 
2076
                         *              n*d / (n - f1 + f1*n/N)
 
2077
                         * where f1 is the number of distinct values that occurred
 
2078
                         * exactly once in our sample of n rows (from a total of N),
 
2079
                         * and d is the total number of distinct values in the sample.
 
2080
                         * This is their Duj1 estimator; the other estimators they
 
2081
                         * recommend are considerably more complex, and are numerically
 
2082
                         * very unstable when n is much smaller than N.
 
2083
                         *
 
2084
                         * We assume (not very reliably!) that all the multiply-occurring
 
2085
                         * values are reflected in the final track[] list, and the other
 
2086
                         * nonnull values all appeared but once.  (XXX this usually
 
2087
                         * results in a drastic overestimate of ndistinct.      Can we do
 
2088
                         * any better?)
 
2089
                         *----------
 
2090
                         */
 
2091
                        int                     f1 = nonnull_cnt - summultiple;
 
2092
                        int                     d = f1 + nmultiple;
 
2093
                        double          numer,
 
2094
                                                denom,
 
2095
                                                stadistinct;
 
2096
 
 
2097
                        numer = (double) samplerows *(double) d;
 
2098
 
 
2099
                        denom = (double) (samplerows - f1) +
 
2100
                                (double) f1 *(double) samplerows / totalrows;
 
2101
 
 
2102
                        stadistinct = numer / denom;
 
2103
                        /* Clamp to sane range in case of roundoff error */
 
2104
                        if (stadistinct < (double) d)
 
2105
                                stadistinct = (double) d;
 
2106
                        if (stadistinct > totalrows)
 
2107
                                stadistinct = totalrows;
 
2108
                        stats->stadistinct = floor(stadistinct + 0.5);
 
2109
                }
 
2110
 
 
2111
                /*
 
2112
                 * If we estimated the number of distinct values at more than 10% of
 
2113
                 * the total row count (a very arbitrary limit), then assume that
 
2114
                 * stadistinct should scale with the row count rather than be a fixed
 
2115
                 * value.
 
2116
                 */
 
2117
                if (stats->stadistinct > 0.1 * totalrows)
 
2118
                        stats->stadistinct = -(stats->stadistinct / totalrows);
 
2119
 
 
2120
                /*
 
2121
                 * Decide how many values are worth storing as most-common values. If
 
2122
                 * we are able to generate a complete MCV list (all the values in the
 
2123
                 * sample will fit, and we think these are all the ones in the table),
 
2124
                 * then do so.  Otherwise, store only those values that are
 
2125
                 * significantly more common than the (estimated) average. We set the
 
2126
                 * threshold rather arbitrarily at 25% more than average, with at
 
2127
                 * least 2 instances in the sample.
 
2128
                 */
 
2129
                if (track_cnt < track_max && toowide_cnt == 0 &&
 
2130
                        stats->stadistinct > 0 &&
 
2131
                        track_cnt <= num_mcv)
 
2132
                {
 
2133
                        /* Track list includes all values seen, and all will fit */
 
2134
                        num_mcv = track_cnt;
 
2135
                }
 
2136
                else
 
2137
                {
 
2138
                        double          ndistinct = stats->stadistinct;
 
2139
                        double          avgcount,
 
2140
                                                mincount;
 
2141
 
 
2142
                        if (ndistinct < 0)
 
2143
                                ndistinct = -ndistinct * totalrows;
 
2144
                        /* estimate # of occurrences in sample of a typical value */
 
2145
                        avgcount = (double) samplerows / ndistinct;
 
2146
                        /* set minimum threshold count to store a value */
 
2147
                        mincount = avgcount * 1.25;
 
2148
                        if (mincount < 2)
 
2149
                                mincount = 2;
 
2150
                        if (num_mcv > track_cnt)
 
2151
                                num_mcv = track_cnt;
 
2152
                        for (i = 0; i < num_mcv; i++)
 
2153
                        {
 
2154
                                if (track[i].count < mincount)
 
2155
                                {
 
2156
                                        num_mcv = i;
 
2157
                                        break;
 
2158
                                }
 
2159
                        }
 
2160
                }
 
2161
 
 
2162
                /* Generate MCV slot entry */
 
2163
                if (num_mcv > 0)
 
2164
                {
 
2165
                        MemoryContext old_context;
 
2166
                        Datum      *mcv_values;
 
2167
                        float4     *mcv_freqs;
 
2168
 
 
2169
                        /* Must copy the target values into anl_context */
 
2170
                        old_context = MemoryContextSwitchTo(stats->anl_context);
 
2171
                        mcv_values = (Datum *) palloc(num_mcv * sizeof(Datum));
 
2172
                        mcv_freqs = (float4 *) palloc(num_mcv * sizeof(float4));
 
2173
                        for (i = 0; i < num_mcv; i++)
 
2174
                        {
 
2175
                                mcv_values[i] = datumCopy(track[i].value,
 
2176
                                                                                  stats->attrtype->typbyval,
 
2177
                                                                                  stats->attrtype->typlen);
 
2178
                                mcv_freqs[i] = (double) track[i].count / (double) samplerows;
 
2179
                        }
 
2180
                        MemoryContextSwitchTo(old_context);
 
2181
 
 
2182
                        stats->stakind[0] = STATISTIC_KIND_MCV;
 
2183
                        stats->staop[0] = mystats->eqopr;
 
2184
                        stats->stanumbers[0] = mcv_freqs;
 
2185
                        stats->numnumbers[0] = num_mcv;
 
2186
                        stats->stavalues[0] = mcv_values;
 
2187
                        stats->numvalues[0] = num_mcv;
 
2188
 
 
2189
                        /*
 
2190
                         * Accept the defaults for stats->statypid and others. They have
 
2191
                         * been set before we were called (see vacuum.h)
 
2192
                         */
 
2193
                }
 
2194
        }
 
2195
        else if (null_cnt > 0)
 
2196
        {
 
2197
                /* We found only nulls; assume the column is entirely null */
 
2198
                stats->stats_valid = true;
 
2199
                stats->stanullfrac = 1.0;
 
2200
                if (is_varwidth)
 
2201
                        stats->stawidth = 0;    /* "unknown" */
 
2202
                else
 
2203
                        stats->stawidth = stats->attrtype->typlen;
 
2204
                stats->stadistinct = 0.0;               /* "unknown" */
 
2205
        }
 
2206
 
 
2207
        /* We don't need to bother cleaning up any of our temporary palloc's */
 
2208
}
 
2209
 
 
2210
 
 
2211
/*
 
2212
 *      compute_scalar_stats() -- compute column statistics
 
2213
 *
 
2214
 *      We use this when we can find "=" and "<" operators for the datatype.
 
2215
 *
 
2216
 *      We determine the fraction of non-null rows, the average width, the
 
2217
 *      most common values, the (estimated) number of distinct values, the
 
2218
 *      distribution histogram, and the correlation of physical to logical order.
 
2219
 *
 
2220
 *      The desired stats can be determined fairly easily after sorting the
 
2221
 *      data values into order.
 
2222
 */
 
2223
static void
 
2224
compute_scalar_stats(VacAttrStatsP stats,
 
2225
                                         AnalyzeAttrFetchFunc fetchfunc,
 
2226
                                         int samplerows,
 
2227
                                         double totalrows)
 
2228
{
 
2229
        int                     i;
 
2230
        int                     null_cnt = 0;
 
2231
        int                     nonnull_cnt = 0;
 
2232
        int                     toowide_cnt = 0;
 
2233
        double          total_width = 0;
 
2234
        bool            is_varlena = (!stats->attrtype->typbyval &&
 
2235
                                                          stats->attrtype->typlen == -1);
 
2236
        bool            is_varwidth = (!stats->attrtype->typbyval &&
 
2237
                                                           stats->attrtype->typlen < 0);
 
2238
        double          corr_xysum;
 
2239
        Oid                     cmpFn;
 
2240
        int                     cmpFlags;
 
2241
        FmgrInfo        f_cmpfn;
 
2242
        ScalarItem *values;
 
2243
        int                     values_cnt = 0;
 
2244
        int                *tupnoLink;
 
2245
        ScalarMCVItem *track;
 
2246
        int                     track_cnt = 0;
 
2247
        int                     num_mcv = stats->attr->attstattarget;
 
2248
        int                     num_bins = stats->attr->attstattarget;
 
2249
        StdAnalyzeData *mystats = (StdAnalyzeData *) stats->extra_data;
 
2250
 
 
2251
        values = (ScalarItem *) palloc(samplerows * sizeof(ScalarItem));
 
2252
        tupnoLink = (int *) palloc(samplerows * sizeof(int));
 
2253
        track = (ScalarMCVItem *) palloc(num_mcv * sizeof(ScalarMCVItem));
 
2254
 
 
2255
        SelectSortFunction(mystats->ltopr, false, &cmpFn, &cmpFlags);
 
2256
        fmgr_info(cmpFn, &f_cmpfn);
 
2257
 
 
2258
        /* Initial scan to find sortable values */
 
2259
        for (i = 0; i < samplerows; i++)
 
2260
        {
 
2261
                Datum           value;
 
2262
                bool            isnull;
 
2263
 
 
2264
                vacuum_delay_point();
 
2265
 
 
2266
                value = fetchfunc(stats, i, &isnull);
 
2267
 
 
2268
                /* Check for null/nonnull */
 
2269
                if (isnull)
 
2270
                {
 
2271
                        null_cnt++;
 
2272
                        continue;
 
2273
                }
 
2274
                nonnull_cnt++;
 
2275
 
 
2276
                /*
 
2277
                 * If it's a variable-width field, add up widths for average width
 
2278
                 * calculation.  Note that if the value is toasted, we use the toasted
 
2279
                 * width.  We don't bother with this calculation if it's a fixed-width
 
2280
                 * type.
 
2281
                 */
 
2282
                if (is_varlena)
 
2283
                {
 
2284
                        total_width += VARSIZE_ANY(DatumGetPointer(value));
 
2285
 
 
2286
                        /*
 
2287
                         * If the value is toasted, we want to detoast it just once to
 
2288
                         * avoid repeated detoastings and resultant excess memory usage
 
2289
                         * during the comparisons.      Also, check to see if the value is
 
2290
                         * excessively wide, and if so don't detoast at all --- just
 
2291
                         * ignore the value.
 
2292
                         */
 
2293
                        if (toast_raw_datum_size(value) > WIDTH_THRESHOLD)
 
2294
                        {
 
2295
                                toowide_cnt++;
 
2296
                                continue;
 
2297
                        }
 
2298
                        value = PointerGetDatum(PG_DETOAST_DATUM(value));
 
2299
                }
 
2300
                else if (is_varwidth)
 
2301
                {
 
2302
                        /* must be cstring */
 
2303
                        total_width += strlen(DatumGetCString(value)) + 1;
 
2304
                }
 
2305
 
 
2306
                /* Add it to the list to be sorted */
 
2307
                values[values_cnt].value = value;
 
2308
                values[values_cnt].tupno = values_cnt;
 
2309
                tupnoLink[values_cnt] = values_cnt;
 
2310
                values_cnt++;
 
2311
        }
 
2312
 
 
2313
        /* We can only compute real stats if we found some sortable values. */
 
2314
        if (values_cnt > 0)
 
2315
        {
 
2316
                int                     ndistinct,      /* # distinct values in sample */
 
2317
                                        nmultiple,      /* # that appear multiple times */
 
2318
                                        num_hist,
 
2319
                                        dups_cnt;
 
2320
                int                     slot_idx = 0;
 
2321
                CompareScalarsContext cxt;
 
2322
 
 
2323
                /* Sort the collected values */
 
2324
                cxt.cmpFn = &f_cmpfn;
 
2325
                cxt.cmpFlags = cmpFlags;
 
2326
                cxt.tupnoLink = tupnoLink;
 
2327
                qsort_arg((void *) values, values_cnt, sizeof(ScalarItem),
 
2328
                                  compare_scalars, (void *) &cxt);
 
2329
 
 
2330
                /*
 
2331
                 * Now scan the values in order, find the most common ones, and also
 
2332
                 * accumulate ordering-correlation statistics.
 
2333
                 *
 
2334
                 * To determine which are most common, we first have to count the
 
2335
                 * number of duplicates of each value.  The duplicates are adjacent in
 
2336
                 * the sorted list, so a brute-force approach is to compare successive
 
2337
                 * datum values until we find two that are not equal. However, that
 
2338
                 * requires N-1 invocations of the datum comparison routine, which are
 
2339
                 * completely redundant with work that was done during the sort.  (The
 
2340
                 * sort algorithm must at some point have compared each pair of items
 
2341
                 * that are adjacent in the sorted order; otherwise it could not know
 
2342
                 * that it's ordered the pair correctly.) We exploit this by having
 
2343
                 * compare_scalars remember the highest tupno index that each
 
2344
                 * ScalarItem has been found equal to.  At the end of the sort, a
 
2345
                 * ScalarItem's tupnoLink will still point to itself if and only if it
 
2346
                 * is the last item of its group of duplicates (since the group will
 
2347
                 * be ordered by tupno).
 
2348
                 */
 
2349
                corr_xysum = 0;
 
2350
                ndistinct = 0;
 
2351
                nmultiple = 0;
 
2352
                dups_cnt = 0;
 
2353
                for (i = 0; i < values_cnt; i++)
 
2354
                {
 
2355
                        int                     tupno = values[i].tupno;
 
2356
 
 
2357
                        corr_xysum += ((double) i) * ((double) tupno);
 
2358
                        dups_cnt++;
 
2359
                        if (tupnoLink[tupno] == tupno)
 
2360
                        {
 
2361
                                /* Reached end of duplicates of this value */
 
2362
                                ndistinct++;
 
2363
                                if (dups_cnt > 1)
 
2364
                                {
 
2365
                                        nmultiple++;
 
2366
                                        if (track_cnt < num_mcv ||
 
2367
                                                dups_cnt > track[track_cnt - 1].count)
 
2368
                                        {
 
2369
                                                /*
 
2370
                                                 * Found a new item for the mcv list; find its
 
2371
                                                 * position, bubbling down old items if needed. Loop
 
2372
                                                 * invariant is that j points at an empty/ replaceable
 
2373
                                                 * slot.
 
2374
                                                 */
 
2375
                                                int                     j;
 
2376
 
 
2377
                                                if (track_cnt < num_mcv)
 
2378
                                                        track_cnt++;
 
2379
                                                for (j = track_cnt - 1; j > 0; j--)
 
2380
                                                {
 
2381
                                                        if (dups_cnt <= track[j - 1].count)
 
2382
                                                                break;
 
2383
                                                        track[j].count = track[j - 1].count;
 
2384
                                                        track[j].first = track[j - 1].first;
 
2385
                                                }
 
2386
                                                track[j].count = dups_cnt;
 
2387
                                                track[j].first = i + 1 - dups_cnt;
 
2388
                                        }
 
2389
                                }
 
2390
                                dups_cnt = 0;
 
2391
                        }
 
2392
                }
 
2393
 
 
2394
                stats->stats_valid = true;
 
2395
                /* Do the simple null-frac and width stats */
 
2396
                stats->stanullfrac = (double) null_cnt / (double) samplerows;
 
2397
                if (is_varwidth)
 
2398
                        stats->stawidth = total_width / (double) nonnull_cnt;
 
2399
                else
 
2400
                        stats->stawidth = stats->attrtype->typlen;
 
2401
 
 
2402
                if (nmultiple == 0)
 
2403
                {
 
2404
                        /* If we found no repeated values, assume it's a unique column */
 
2405
                        stats->stadistinct = -1.0;
 
2406
                }
 
2407
                else if (toowide_cnt == 0 && nmultiple == ndistinct)
 
2408
                {
 
2409
                        /*
 
2410
                         * Every value in the sample appeared more than once.  Assume the
 
2411
                         * column has just these values.
 
2412
                         */
 
2413
                        stats->stadistinct = ndistinct;
 
2414
                }
 
2415
                else
 
2416
                {
 
2417
                        /*----------
 
2418
                         * Estimate the number of distinct values using the estimator
 
2419
                         * proposed by Haas and Stokes in IBM Research Report RJ 10025:
 
2420
                         *              n*d / (n - f1 + f1*n/N)
 
2421
                         * where f1 is the number of distinct values that occurred
 
2422
                         * exactly once in our sample of n rows (from a total of N),
 
2423
                         * and d is the total number of distinct values in the sample.
 
2424
                         * This is their Duj1 estimator; the other estimators they
 
2425
                         * recommend are considerably more complex, and are numerically
 
2426
                         * very unstable when n is much smaller than N.
 
2427
                         *
 
2428
                         * Overwidth values are assumed to have been distinct.
 
2429
                         *----------
 
2430
                         */
 
2431
                        int                     f1 = ndistinct - nmultiple + toowide_cnt;
 
2432
                        int                     d = f1 + nmultiple;
 
2433
                        double          numer,
 
2434
                                                denom,
 
2435
                                                stadistinct;
 
2436
 
 
2437
                        numer = (double) samplerows *(double) d;
 
2438
 
 
2439
                        denom = (double) (samplerows - f1) +
 
2440
                                (double) f1 *(double) samplerows / totalrows;
 
2441
 
 
2442
                        stadistinct = numer / denom;
 
2443
                        /* Clamp to sane range in case of roundoff error */
 
2444
                        if (stadistinct < (double) d)
 
2445
                                stadistinct = (double) d;
 
2446
                        if (stadistinct > totalrows)
 
2447
                                stadistinct = totalrows;
 
2448
                        stats->stadistinct = floor(stadistinct + 0.5);
 
2449
                }
 
2450
 
 
2451
                /*
 
2452
                 * If we estimated the number of distinct values at more than 10% of
 
2453
                 * the total row count (a very arbitrary limit), then assume that
 
2454
                 * stadistinct should scale with the row count rather than be a fixed
 
2455
                 * value.
 
2456
                 */
 
2457
                if (stats->stadistinct > 0.1 * totalrows)
 
2458
                        stats->stadistinct = -(stats->stadistinct / totalrows);
 
2459
 
 
2460
                /*
 
2461
                 * Decide how many values are worth storing as most-common values. If
 
2462
                 * we are able to generate a complete MCV list (all the values in the
 
2463
                 * sample will fit, and we think these are all the ones in the table),
 
2464
                 * then do so.  Otherwise, store only those values that are
 
2465
                 * significantly more common than the (estimated) average. We set the
 
2466
                 * threshold rather arbitrarily at 25% more than average, with at
 
2467
                 * least 2 instances in the sample.  Also, we won't suppress values
 
2468
                 * that have a frequency of at least 1/K where K is the intended
 
2469
                 * number of histogram bins; such values might otherwise cause us to
 
2470
                 * emit duplicate histogram bin boundaries.  (We might end up with
 
2471
                 * duplicate histogram entries anyway, if the distribution is skewed;
 
2472
                 * but we prefer to treat such values as MCVs if at all possible.)
 
2473
                 */
 
2474
                if (track_cnt == ndistinct && toowide_cnt == 0 &&
 
2475
                        stats->stadistinct > 0 &&
 
2476
                        track_cnt <= num_mcv)
 
2477
                {
 
2478
                        /* Track list includes all values seen, and all will fit */
 
2479
                        num_mcv = track_cnt;
 
2480
                }
 
2481
                else
 
2482
                {
 
2483
                        double          ndistinct = stats->stadistinct;
 
2484
                        double          avgcount,
 
2485
                                                mincount,
 
2486
                                                maxmincount;
 
2487
 
 
2488
                        if (ndistinct < 0)
 
2489
                                ndistinct = -ndistinct * totalrows;
 
2490
                        /* estimate # of occurrences in sample of a typical value */
 
2491
                        avgcount = (double) samplerows / ndistinct;
 
2492
                        /* set minimum threshold count to store a value */
 
2493
                        mincount = avgcount * 1.25;
 
2494
                        if (mincount < 2)
 
2495
                                mincount = 2;
 
2496
                        /* don't let threshold exceed 1/K, however */
 
2497
                        maxmincount = (double) samplerows / (double) num_bins;
 
2498
                        if (mincount > maxmincount)
 
2499
                                mincount = maxmincount;
 
2500
                        if (num_mcv > track_cnt)
 
2501
                                num_mcv = track_cnt;
 
2502
                        for (i = 0; i < num_mcv; i++)
 
2503
                        {
 
2504
                                if (track[i].count < mincount)
 
2505
                                {
 
2506
                                        num_mcv = i;
 
2507
                                        break;
 
2508
                                }
 
2509
                        }
 
2510
                }
 
2511
 
 
2512
                /* Generate MCV slot entry */
 
2513
                if (num_mcv > 0)
 
2514
                {
 
2515
                        MemoryContext old_context;
 
2516
                        Datum      *mcv_values;
 
2517
                        float4     *mcv_freqs;
 
2518
 
 
2519
                        /* Must copy the target values into anl_context */
 
2520
                        old_context = MemoryContextSwitchTo(stats->anl_context);
 
2521
                        mcv_values = (Datum *) palloc(num_mcv * sizeof(Datum));
 
2522
                        mcv_freqs = (float4 *) palloc(num_mcv * sizeof(float4));
 
2523
                        for (i = 0; i < num_mcv; i++)
 
2524
                        {
 
2525
                                mcv_values[i] = datumCopy(values[track[i].first].value,
 
2526
                                                                                  stats->attrtype->typbyval,
 
2527
                                                                                  stats->attrtype->typlen);
 
2528
                                mcv_freqs[i] = (double) track[i].count / (double) samplerows;
 
2529
                        }
 
2530
                        MemoryContextSwitchTo(old_context);
 
2531
 
 
2532
                        stats->stakind[slot_idx] = STATISTIC_KIND_MCV;
 
2533
                        stats->staop[slot_idx] = mystats->eqopr;
 
2534
                        stats->stanumbers[slot_idx] = mcv_freqs;
 
2535
                        stats->numnumbers[slot_idx] = num_mcv;
 
2536
                        stats->stavalues[slot_idx] = mcv_values;
 
2537
                        stats->numvalues[slot_idx] = num_mcv;
 
2538
 
 
2539
                        /*
 
2540
                         * Accept the defaults for stats->statypid and others. They have
 
2541
                         * been set before we were called (see vacuum.h)
 
2542
                         */
 
2543
                        slot_idx++;
 
2544
                }
 
2545
 
 
2546
                /*
 
2547
                 * Generate a histogram slot entry if there are at least two distinct
 
2548
                 * values not accounted for in the MCV list.  (This ensures the
 
2549
                 * histogram won't collapse to empty or a singleton.)
 
2550
                 */
 
2551
                num_hist = ndistinct - num_mcv;
 
2552
                if (num_hist > num_bins)
 
2553
                        num_hist = num_bins + 1;
 
2554
                if (num_hist >= 2)
 
2555
                {
 
2556
                        MemoryContext old_context;
 
2557
                        Datum      *hist_values;
 
2558
                        int                     nvals;
 
2559
                        int                     pos,
 
2560
                                                posfrac,
 
2561
                                                delta,
 
2562
                                                deltafrac;
 
2563
 
 
2564
                        /* Sort the MCV items into position order to speed next loop */
 
2565
                        qsort((void *) track, num_mcv,
 
2566
                                  sizeof(ScalarMCVItem), compare_mcvs);
 
2567
 
 
2568
                        /*
 
2569
                         * Collapse out the MCV items from the values[] array.
 
2570
                         *
 
2571
                         * Note we destroy the values[] array here... but we don't need it
 
2572
                         * for anything more.  We do, however, still need values_cnt.
 
2573
                         * nvals will be the number of remaining entries in values[].
 
2574
                         */
 
2575
                        if (num_mcv > 0)
 
2576
                        {
 
2577
                                int                     src,
 
2578
                                                        dest;
 
2579
                                int                     j;
 
2580
 
 
2581
                                src = dest = 0;
 
2582
                                j = 0;                  /* index of next interesting MCV item */
 
2583
                                while (src < values_cnt)
 
2584
                                {
 
2585
                                        int                     ncopy;
 
2586
 
 
2587
                                        if (j < num_mcv)
 
2588
                                        {
 
2589
                                                int                     first = track[j].first;
 
2590
 
 
2591
                                                if (src >= first)
 
2592
                                                {
 
2593
                                                        /* advance past this MCV item */
 
2594
                                                        src = first + track[j].count;
 
2595
                                                        j++;
 
2596
                                                        continue;
 
2597
                                                }
 
2598
                                                ncopy = first - src;
 
2599
                                        }
 
2600
                                        else
 
2601
                                                ncopy = values_cnt - src;
 
2602
                                        memmove(&values[dest], &values[src],
 
2603
                                                        ncopy * sizeof(ScalarItem));
 
2604
                                        src += ncopy;
 
2605
                                        dest += ncopy;
 
2606
                                }
 
2607
                                nvals = dest;
 
2608
                        }
 
2609
                        else
 
2610
                                nvals = values_cnt;
 
2611
                        Assert(nvals >= num_hist);
 
2612
 
 
2613
                        /* Must copy the target values into anl_context */
 
2614
                        old_context = MemoryContextSwitchTo(stats->anl_context);
 
2615
                        hist_values = (Datum *) palloc(num_hist * sizeof(Datum));
 
2616
 
 
2617
                        /*
 
2618
                         * The object of this loop is to copy the first and last values[]
 
2619
                         * entries along with evenly-spaced values in between.  So the
 
2620
                         * i'th value is values[(i * (nvals - 1)) / (num_hist - 1)].  But
 
2621
                         * computing that subscript directly risks integer overflow when
 
2622
                         * the stats target is more than a couple thousand.  Instead we
 
2623
                         * add (nvals - 1) / (num_hist - 1) to pos at each step, tracking
 
2624
                         * the integral and fractional parts of the sum separately.
 
2625
                         */
 
2626
                        delta = (nvals - 1) / (num_hist - 1);
 
2627
                        deltafrac = (nvals - 1) % (num_hist - 1);
 
2628
                        pos = posfrac = 0;
 
2629
 
 
2630
                        for (i = 0; i < num_hist; i++)
 
2631
                        {
 
2632
                                hist_values[i] = datumCopy(values[pos].value,
 
2633
                                                                                   stats->attrtype->typbyval,
 
2634
                                                                                   stats->attrtype->typlen);
 
2635
                                pos += delta;
 
2636
                                posfrac += deltafrac;
 
2637
                                if (posfrac >= (num_hist - 1))
 
2638
                                {
 
2639
                                        /* fractional part exceeds 1, carry to integer part */
 
2640
                                        pos++;
 
2641
                                        posfrac -= (num_hist - 1);
 
2642
                                }
 
2643
                        }
 
2644
 
 
2645
                        MemoryContextSwitchTo(old_context);
 
2646
 
 
2647
                        stats->stakind[slot_idx] = STATISTIC_KIND_HISTOGRAM;
 
2648
                        stats->staop[slot_idx] = mystats->ltopr;
 
2649
                        stats->stavalues[slot_idx] = hist_values;
 
2650
                        stats->numvalues[slot_idx] = num_hist;
 
2651
 
 
2652
                        /*
 
2653
                         * Accept the defaults for stats->statypid and others. They have
 
2654
                         * been set before we were called (see vacuum.h)
 
2655
                         */
 
2656
                        slot_idx++;
 
2657
                }
 
2658
 
 
2659
                /* Generate a correlation entry if there are multiple values */
 
2660
                if (values_cnt > 1)
 
2661
                {
 
2662
                        MemoryContext old_context;
 
2663
                        float4     *corrs;
 
2664
                        double          corr_xsum,
 
2665
                                                corr_x2sum;
 
2666
 
 
2667
                        /* Must copy the target values into anl_context */
 
2668
                        old_context = MemoryContextSwitchTo(stats->anl_context);
 
2669
                        corrs = (float4 *) palloc(sizeof(float4));
 
2670
                        MemoryContextSwitchTo(old_context);
 
2671
 
 
2672
                        /*----------
 
2673
                         * Since we know the x and y value sets are both
 
2674
                         *              0, 1, ..., values_cnt-1
 
2675
                         * we have sum(x) = sum(y) =
 
2676
                         *              (values_cnt-1)*values_cnt / 2
 
2677
                         * and sum(x^2) = sum(y^2) =
 
2678
                         *              (values_cnt-1)*values_cnt*(2*values_cnt-1) / 6.
 
2679
                         *----------
 
2680
                         */
 
2681
                        corr_xsum = ((double) (values_cnt - 1)) *
 
2682
                                ((double) values_cnt) / 2.0;
 
2683
                        corr_x2sum = ((double) (values_cnt - 1)) *
 
2684
                                ((double) values_cnt) * (double) (2 * values_cnt - 1) / 6.0;
 
2685
 
 
2686
                        /* And the correlation coefficient reduces to */
 
2687
                        corrs[0] = (values_cnt * corr_xysum - corr_xsum * corr_xsum) /
 
2688
                                (values_cnt * corr_x2sum - corr_xsum * corr_xsum);
 
2689
 
 
2690
                        stats->stakind[slot_idx] = STATISTIC_KIND_CORRELATION;
 
2691
                        stats->staop[slot_idx] = mystats->ltopr;
 
2692
                        stats->stanumbers[slot_idx] = corrs;
 
2693
                        stats->numnumbers[slot_idx] = 1;
 
2694
                        slot_idx++;
 
2695
                }
 
2696
        }
 
2697
        else if (nonnull_cnt == 0 && null_cnt > 0)
 
2698
        {
 
2699
                /* We found only nulls; assume the column is entirely null */
 
2700
                stats->stats_valid = true;
 
2701
                stats->stanullfrac = 1.0;
 
2702
                if (is_varwidth)
 
2703
                        stats->stawidth = 0;    /* "unknown" */
 
2704
                else
 
2705
                        stats->stawidth = stats->attrtype->typlen;
 
2706
                stats->stadistinct = 0.0;               /* "unknown" */
 
2707
        }
 
2708
 
 
2709
        /* We don't need to bother cleaning up any of our temporary palloc's */
 
2710
}
 
2711
 
 
2712
/*
 
2713
 * qsort_arg comparator for sorting ScalarItems
 
2714
 *
 
2715
 * Aside from sorting the items, we update the tupnoLink[] array
 
2716
 * whenever two ScalarItems are found to contain equal datums.  The array
 
2717
 * is indexed by tupno; for each ScalarItem, it contains the highest
 
2718
 * tupno that that item's datum has been found to be equal to.  This allows
 
2719
 * us to avoid additional comparisons in compute_scalar_stats().
 
2720
 */
 
2721
static int
 
2722
compare_scalars(const void *a, const void *b, void *arg)
 
2723
{
 
2724
        Datum           da = ((ScalarItem *) a)->value;
 
2725
        int                     ta = ((ScalarItem *) a)->tupno;
 
2726
        Datum           db = ((ScalarItem *) b)->value;
 
2727
        int                     tb = ((ScalarItem *) b)->tupno;
 
2728
        CompareScalarsContext *cxt = (CompareScalarsContext *) arg;
 
2729
        int32           compare;
 
2730
 
 
2731
        /* We always use the default collation for statistics */
 
2732
        compare = ApplySortFunction(cxt->cmpFn, cxt->cmpFlags,
 
2733
                                                                DEFAULT_COLLATION_OID,
 
2734
                                                                da, false, db, false);
 
2735
        if (compare != 0)
 
2736
                return compare;
 
2737
 
 
2738
        /*
 
2739
         * The two datums are equal, so update cxt->tupnoLink[].
 
2740
         */
 
2741
        if (cxt->tupnoLink[ta] < tb)
 
2742
                cxt->tupnoLink[ta] = tb;
 
2743
        if (cxt->tupnoLink[tb] < ta)
 
2744
                cxt->tupnoLink[tb] = ta;
 
2745
 
 
2746
        /*
 
2747
         * For equal datums, sort by tupno
 
2748
         */
 
2749
        return ta - tb;
 
2750
}
 
2751
 
 
2752
/*
 
2753
 * qsort comparator for sorting ScalarMCVItems by position
 
2754
 */
 
2755
static int
 
2756
compare_mcvs(const void *a, const void *b)
 
2757
{
 
2758
        int                     da = ((ScalarMCVItem *) a)->first;
 
2759
        int                     db = ((ScalarMCVItem *) b)->first;
 
2760
 
 
2761
        return da - db;
 
2762
}