Coverage Report

Created: 2026-11-09 07:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/commands/analyze.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * analyze.c
4
 *    the Postgres statistics generator
5
 *
6
 * Portions Copyright (c) 1996-2026, 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/detoast.h"
20
#include "access/genam.h"
21
#include "access/multixact.h"
22
#include "access/relation.h"
23
#include "access/table.h"
24
#include "access/tableam.h"
25
#include "access/transam.h"
26
#include "access/tupconvert.h"
27
#include "access/visibilitymap.h"
28
#include "access/xact.h"
29
#include "catalog/index.h"
30
#include "catalog/indexing.h"
31
#include "catalog/pg_inherits.h"
32
#include "commands/progress.h"
33
#include "commands/tablecmds.h"
34
#include "commands/vacuum.h"
35
#include "common/pg_prng.h"
36
#include "executor/executor.h"
37
#include "executor/instrument.h"
38
#include "foreign/fdwapi.h"
39
#include "miscadmin.h"
40
#include "nodes/nodeFuncs.h"
41
#include "parser/parse_oper.h"
42
#include "parser/parse_relation.h"
43
#include "pgstat.h"
44
#include "statistics/extended_stats_internal.h"
45
#include "statistics/statistics.h"
46
#include "storage/bufmgr.h"
47
#include "storage/procarray.h"
48
#include "utils/attoptcache.h"
49
#include "utils/datum.h"
50
#include "utils/guc.h"
51
#include "utils/lsyscache.h"
52
#include "utils/memutils.h"
53
#include "utils/pg_rusage.h"
54
#include "utils/sampling.h"
55
#include "utils/sortsupport.h"
56
#include "utils/syscache.h"
57
#include "utils/timestamp.h"
58
59
60
/* Per-index data for ANALYZE */
61
typedef struct AnlIndexData
62
{
63
  IndexInfo  *indexInfo;    /* BuildIndexInfo result */
64
  double    tupleFract;   /* fraction of rows for partial index */
65
  VacAttrStats **vacattrstats;  /* index attrs to analyze */
66
  int     attr_cnt;
67
} AnlIndexData;
68
69
70
/* Default statistics target (GUC parameter) */
71
int     default_statistics_target = 100;
72
73
/* A few variables that don't seem worth passing around as parameters */
74
static MemoryContext anl_context = NULL;
75
static BufferAccessStrategy vac_strategy;
76
77
78
static void do_analyze_rel(Relation onerel,
79
               const VacuumParams *params, List *va_cols,
80
               AcquireSampleRowsFunc acquirefunc, BlockNumber relpages,
81
               bool inh, bool in_outer_xact, int elevel);
82
static void compute_index_stats(Relation onerel, double totalrows,
83
                AnlIndexData *indexdata, int nindexes,
84
                HeapTuple *rows, int numrows,
85
                MemoryContext col_context);
86
static void validate_va_cols_list(Relation onerel, List *va_cols);
87
static VacAttrStats *examine_attribute(Relation onerel, int attnum,
88
                     Node *index_expr);
89
static int  acquire_sample_rows(Relation onerel, int elevel,
90
                HeapTuple *rows, int targrows,
91
                double *totalrows, double *totaldeadrows);
92
static int  compare_rows(const void *a, const void *b, void *arg);
93
static int  acquire_inherited_sample_rows(Relation onerel, int elevel,
94
                      HeapTuple *rows, int targrows,
95
                      double *totalrows, double *totaldeadrows);
96
static void update_attstats(Oid relid, bool inh,
97
              int natts, VacAttrStats **vacattrstats);
98
static Datum std_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
99
static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
100
101
102
/*
103
 *  analyze_rel() -- analyze one relation
104
 *
105
 * relid identifies the relation to analyze.  If relation is supplied, use
106
 * the name therein for reporting any failure to open/lock the rel; do not
107
 * use it once we've successfully opened the rel, since it might be stale.
108
 */
109
void
110
analyze_rel(Oid relid, RangeVar *relation,
111
      const VacuumParams *params, List *va_cols, bool in_outer_xact,
112
      BufferAccessStrategy bstrategy)
113
0
{
114
0
  Relation  onerel;
115
0
  int     elevel;
116
0
  AcquireSampleRowsFunc acquirefunc = NULL;
117
0
  BlockNumber relpages = 0;
118
0
  bool    stats_imported = false;
119
120
  /* Select logging level */
121
0
  if (params->options & VACOPT_VERBOSE)
122
0
    elevel = INFO;
123
0
  else
124
0
    elevel = DEBUG2;
125
126
  /* Set up static variables */
127
0
  vac_strategy = bstrategy;
128
129
  /*
130
   * Check for user-requested abort.
131
   */
132
0
  CHECK_FOR_INTERRUPTS();
133
134
  /*
135
   * Open the relation, getting ShareUpdateExclusiveLock to ensure that two
136
   * ANALYZEs don't run on it concurrently.  (This also locks out a
137
   * concurrent VACUUM, which doesn't matter much at the moment but might
138
   * matter if we ever try to accumulate stats on dead tuples.) If the rel
139
   * has been dropped since we last saw it, we don't need to process it.
140
   *
141
   * Make sure to generate only logs for ANALYZE in this case.
142
   */
143
0
  onerel = vacuum_open_relation(relid, relation, params->options & ~(VACOPT_VACUUM),
144
0
                  params->log_analyze_min_duration >= 0,
145
0
                  ShareUpdateExclusiveLock);
146
147
  /* leave if relation could not be opened or locked */
148
0
  if (!onerel)
149
0
    return;
150
151
  /*
152
   * Check if relation needs to be skipped based on privileges.  This check
153
   * happens also when building the relation list to analyze for a manual
154
   * operation, and needs to be done additionally here as ANALYZE could
155
   * happen across multiple transactions where privileges could have changed
156
   * in-between.  Make sure to generate only logs for ANALYZE in this case.
157
   */
158
0
  if (!vacuum_is_permitted_for_relation(RelationGetRelid(onerel),
159
0
                      onerel->rd_rel,
160
0
                      params->options & ~VACOPT_VACUUM,
161
0
                      false))
162
0
  {
163
0
    relation_close(onerel, ShareUpdateExclusiveLock);
164
0
    return;
165
0
  }
166
167
  /*
168
   * Silently ignore tables that are temp tables of other backends ---
169
   * trying to analyze these is rather pointless, since their contents are
170
   * probably not up-to-date on disk.  (We don't throw a warning here; it
171
   * would just lead to chatter during a database-wide ANALYZE.)
172
   */
173
0
  if (RELATION_IS_OTHER_TEMP(onerel))
174
0
  {
175
0
    relation_close(onerel, ShareUpdateExclusiveLock);
176
0
    return;
177
0
  }
178
179
  /*
180
   * We can ANALYZE any table except pg_statistic. See update_attstats
181
   */
182
0
  if (RelationGetRelid(onerel) == StatisticRelationId)
183
0
  {
184
0
    relation_close(onerel, ShareUpdateExclusiveLock);
185
0
    return;
186
0
  }
187
188
  /*
189
   * Check the given list of columns
190
   */
191
0
  if (va_cols != NIL)
192
0
    validate_va_cols_list(onerel, va_cols);
193
194
  /*
195
   * Initialize progress reporting before setup for regular/foreign tables.
196
   * (For the former, the time spent on it would be negligible, but for the
197
   * latter, if FDWs support statistics import or analysis, they'd do some
198
   * work that needs the remote access, so the time might be
199
   * non-negligible.)
200
   */
201
0
  pgstat_progress_start_command(PROGRESS_COMMAND_ANALYZE,
202
0
                  RelationGetRelid(onerel));
203
0
  if (AmAutoVacuumWorkerProcess())
204
0
    pgstat_progress_update_param(PROGRESS_ANALYZE_STARTED_BY,
205
0
                   PROGRESS_ANALYZE_STARTED_BY_AUTOVACUUM);
206
0
  else
207
0
    pgstat_progress_update_param(PROGRESS_ANALYZE_STARTED_BY,
208
0
                   PROGRESS_ANALYZE_STARTED_BY_MANUAL);
209
210
  /*
211
   * Check that it's of an analyzable relkind, and set up appropriately.
212
   */
213
0
  if (onerel->rd_rel->relkind == RELKIND_RELATION ||
214
0
    onerel->rd_rel->relkind == RELKIND_MATVIEW)
215
0
  {
216
    /* Regular table, so we'll use the regular row acquisition function */
217
0
    acquirefunc = acquire_sample_rows;
218
    /* Also get regular table's size */
219
0
    relpages = RelationGetNumberOfBlocks(onerel);
220
0
  }
221
0
  else if (onerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
222
0
  {
223
    /*
224
     * For a foreign table, call the FDW's hook functions to see whether
225
     * it supports statistics import or analysis.
226
     */
227
0
    FdwRoutine *fdwroutine;
228
229
0
    fdwroutine = GetFdwRoutineForRelation(onerel, false);
230
231
0
    if (fdwroutine->ImportForeignStatistics != NULL)
232
0
    {
233
0
      Oid     save_userid;
234
0
      int     save_sec_context;
235
0
      int     save_nestlevel;
236
237
      /*
238
       * Switch to the table owner's userid, as in the sampling path.
239
       * Also lock down security-restricted operations and arrange to
240
       * make GUC variable changes local to this command.
241
       */
242
0
      GetUserIdAndSecContext(&save_userid, &save_sec_context);
243
0
      SetUserIdAndSecContext(onerel->rd_rel->relowner,
244
0
                   save_sec_context | SECURITY_RESTRICTED_OPERATION);
245
0
      save_nestlevel = NewGUCNestLevel();
246
0
      RestrictSearchPath();
247
248
0
      stats_imported = fdwroutine->ImportForeignStatistics(onerel,
249
0
                                 va_cols,
250
0
                                 elevel);
251
252
0
      AtEOXact_GUC(false, save_nestlevel);
253
0
      SetUserIdAndSecContext(save_userid, save_sec_context);
254
0
    }
255
256
0
    if (!stats_imported)
257
0
    {
258
0
      bool    ok = false;
259
260
0
      if (fdwroutine->AnalyzeForeignTable != NULL)
261
0
        ok = fdwroutine->AnalyzeForeignTable(onerel,
262
0
                           &acquirefunc,
263
0
                           &relpages);
264
265
0
      if (!ok)
266
0
      {
267
0
        ereport(WARNING,
268
0
            errmsg("skipping \"%s\" --- cannot analyze this foreign table",
269
0
                 RelationGetRelationName(onerel)));
270
0
        relation_close(onerel, ShareUpdateExclusiveLock);
271
0
        goto out;
272
0
      }
273
0
    }
274
0
  }
275
0
  else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
276
0
  {
277
    /*
278
     * For partitioned tables, we want to do the recursive ANALYZE below.
279
     */
280
0
  }
281
0
  else
282
0
  {
283
    /* No need for a WARNING if we already complained during VACUUM */
284
0
    if (!(params->options & VACOPT_VACUUM))
285
0
      ereport(WARNING,
286
0
          (errmsg("skipping \"%s\" --- cannot analyze non-tables or special system tables",
287
0
              RelationGetRelationName(onerel))));
288
0
    relation_close(onerel, ShareUpdateExclusiveLock);
289
0
    goto out;
290
0
  }
291
292
  /*
293
   * Do the normal non-recursive ANALYZE.  We can skip this for partitioned
294
   * tables, which don't contain any rows, and foreign tables that
295
   * successfully imported statistics.
296
   */
297
0
  if ((onerel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
298
0
    && !stats_imported)
299
0
    do_analyze_rel(onerel, params, va_cols, acquirefunc,
300
0
             relpages, false, in_outer_xact, elevel);
301
302
  /*
303
   * If there are child tables, do recursive ANALYZE.
304
   */
305
0
  if (onerel->rd_rel->relhassubclass)
306
0
    do_analyze_rel(onerel, params, va_cols, acquirefunc, relpages,
307
0
             true, in_outer_xact, elevel);
308
309
  /*
310
   * Close source relation now, but keep lock so that no one deletes it
311
   * before we commit.  (If someone did, they'd fail to clean up the entries
312
   * we made in pg_statistic.  Also, releasing the lock before commit would
313
   * expose us to concurrent-update failures in update_attstats.)
314
   */
315
0
  relation_close(onerel, NoLock);
316
317
0
out:
318
0
  pgstat_progress_end_command();
319
0
}
320
321
/*
322
 *  do_analyze_rel() -- analyze one relation, recursively or not
323
 *
324
 * Note that "acquirefunc" is only relevant for the non-inherited case.
325
 * For the inherited case, acquire_inherited_sample_rows() determines the
326
 * appropriate acquirefunc for each child table.
327
 */
328
static void
329
do_analyze_rel(Relation onerel, const VacuumParams *params,
330
         List *va_cols, AcquireSampleRowsFunc acquirefunc,
331
         BlockNumber relpages, bool inh, bool in_outer_xact,
332
         int elevel)
333
0
{
334
0
  int     attr_cnt,
335
0
        tcnt,
336
0
        i,
337
0
        ind;
338
0
  Relation   *Irel;
339
0
  int     nindexes;
340
0
  bool    verbose,
341
0
        instrument,
342
0
        hasindex;
343
0
  VacAttrStats **vacattrstats;
344
0
  AnlIndexData *indexdata;
345
0
  int     targrows,
346
0
        numrows,
347
0
        minrows;
348
0
  double    totalrows,
349
0
        totaldeadrows;
350
0
  HeapTuple  *rows;
351
0
  PGRUsage  ru0;
352
0
  TimestampTz starttime = 0;
353
0
  MemoryContext caller_context;
354
0
  Oid     save_userid;
355
0
  int     save_sec_context;
356
0
  int     save_nestlevel;
357
0
  WalUsage  startwalusage = pgWalUsage;
358
0
  BufferUsage startbufferusage = pgBufferUsage;
359
0
  BufferUsage bufferusage;
360
0
  PgStat_Counter startreadtime = 0;
361
0
  PgStat_Counter startwritetime = 0;
362
363
0
  verbose = (params->options & VACOPT_VERBOSE) != 0;
364
0
  instrument = (verbose || (AmAutoVacuumWorkerProcess() &&
365
0
                params->log_analyze_min_duration >= 0));
366
0
  if (inh)
367
0
    ereport(elevel,
368
0
        (errmsg("analyzing \"%s.%s\" inheritance tree",
369
0
            get_namespace_name(RelationGetNamespace(onerel)),
370
0
            RelationGetRelationName(onerel))));
371
0
  else
372
0
    ereport(elevel,
373
0
        (errmsg("analyzing \"%s.%s\"",
374
0
            get_namespace_name(RelationGetNamespace(onerel)),
375
0
            RelationGetRelationName(onerel))));
376
377
  /*
378
   * Set up a working context so that we can easily free whatever junk gets
379
   * created.
380
   */
381
0
  anl_context = AllocSetContextCreate(CurrentMemoryContext,
382
0
                    "Analyze",
383
0
                    ALLOCSET_DEFAULT_SIZES);
384
0
  caller_context = MemoryContextSwitchTo(anl_context);
385
386
  /*
387
   * Switch to the table owner's userid, so that any index functions are run
388
   * as that user.  Also lock down security-restricted operations and
389
   * arrange to make GUC variable changes local to this command.
390
   */
391
0
  GetUserIdAndSecContext(&save_userid, &save_sec_context);
392
0
  SetUserIdAndSecContext(onerel->rd_rel->relowner,
393
0
               save_sec_context | SECURITY_RESTRICTED_OPERATION);
394
0
  save_nestlevel = NewGUCNestLevel();
395
0
  RestrictSearchPath();
396
397
  /*
398
   * When verbose or autovacuum logging is used, initialize a resource usage
399
   * snapshot and optionally track I/O timing.
400
   */
401
0
  if (instrument)
402
0
  {
403
0
    if (track_io_timing)
404
0
    {
405
0
      startreadtime = pgStatBlockReadTime;
406
0
      startwritetime = pgStatBlockWriteTime;
407
0
    }
408
409
0
    pg_rusage_init(&ru0);
410
0
  }
411
412
  /* Used for instrumentation and stats report */
413
0
  starttime = GetCurrentTimestamp();
414
415
  /*
416
   * Determine which columns to analyze.
417
   */
418
0
  if (va_cols != NIL)
419
0
  {
420
0
    ListCell   *le;
421
422
0
    vacattrstats = palloc_array(VacAttrStats *, list_length(va_cols));
423
0
    tcnt = 0;
424
0
    foreach(le, va_cols)
425
0
    {
426
0
      char     *col = strVal(lfirst(le));
427
428
0
      i = attnameAttNum(onerel, col, false);
429
0
      Assert(i != InvalidAttrNumber);
430
0
      vacattrstats[tcnt] = examine_attribute(onerel, i, NULL);
431
0
      if (vacattrstats[tcnt] != NULL)
432
0
        tcnt++;
433
0
    }
434
0
    attr_cnt = tcnt;
435
0
  }
436
0
  else
437
0
  {
438
0
    attr_cnt = onerel->rd_att->natts;
439
0
    vacattrstats = palloc_array(VacAttrStats *, attr_cnt);
440
0
    tcnt = 0;
441
0
    for (i = 1; i <= attr_cnt; i++)
442
0
    {
443
0
      vacattrstats[tcnt] = examine_attribute(onerel, i, NULL);
444
0
      if (vacattrstats[tcnt] != NULL)
445
0
        tcnt++;
446
0
    }
447
0
    attr_cnt = tcnt;
448
0
  }
449
450
  /*
451
   * Open all indexes of the relation, and see if there are any analyzable
452
   * columns in the indexes.  We do not analyze index columns if there was
453
   * an explicit column list in the ANALYZE command, however.
454
   *
455
   * If we are doing a recursive scan, we don't want to touch the parent's
456
   * indexes at all.  If we're processing a partitioned table, we need to
457
   * know if there are any indexes, but we don't want to process them.
458
   */
459
0
  if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
460
0
  {
461
0
    List     *idxs = RelationGetIndexList(onerel);
462
463
0
    Irel = NULL;
464
0
    nindexes = 0;
465
0
    hasindex = idxs != NIL;
466
0
    list_free(idxs);
467
0
  }
468
0
  else if (!inh)
469
0
  {
470
0
    vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
471
0
    hasindex = nindexes > 0;
472
0
  }
473
0
  else
474
0
  {
475
0
    Irel = NULL;
476
0
    nindexes = 0;
477
0
    hasindex = false;
478
0
  }
479
0
  indexdata = NULL;
480
0
  if (nindexes > 0)
481
0
  {
482
0
    indexdata = palloc0_array(AnlIndexData, nindexes);
483
0
    for (ind = 0; ind < nindexes; ind++)
484
0
    {
485
0
      AnlIndexData *thisdata = &indexdata[ind];
486
0
      IndexInfo  *indexInfo;
487
488
0
      thisdata->indexInfo = indexInfo = BuildIndexInfo(Irel[ind]);
489
0
      thisdata->tupleFract = 1.0; /* fix later if partial */
490
0
      if (indexInfo->ii_Expressions != NIL && va_cols == NIL)
491
0
      {
492
0
        ListCell   *indexpr_item = list_head(indexInfo->ii_Expressions);
493
494
0
        thisdata->vacattrstats = palloc_array(VacAttrStats *,
495
0
                            indexInfo->ii_NumIndexAttrs);
496
0
        tcnt = 0;
497
0
        for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
498
0
        {
499
0
          int     keycol = indexInfo->ii_IndexAttrNumbers[i];
500
501
0
          if (keycol == 0)
502
0
          {
503
            /* Found an index expression */
504
0
            Node     *indexkey;
505
506
0
            if (indexpr_item == NULL) /* shouldn't happen */
507
0
              elog(ERROR, "too few entries in indexprs list");
508
0
            indexkey = (Node *) lfirst(indexpr_item);
509
0
            indexpr_item = lnext(indexInfo->ii_Expressions,
510
0
                       indexpr_item);
511
0
            thisdata->vacattrstats[tcnt] =
512
0
              examine_attribute(Irel[ind], i + 1, indexkey);
513
0
            if (thisdata->vacattrstats[tcnt] != NULL)
514
0
              tcnt++;
515
0
          }
516
0
        }
517
0
        thisdata->attr_cnt = tcnt;
518
0
      }
519
0
    }
520
0
  }
521
522
  /*
523
   * Determine how many rows we need to sample, using the worst case from
524
   * all analyzable columns.  We use a lower bound of 100 rows to avoid
525
   * possible overflow in Vitter's algorithm.  (Note: that will also be the
526
   * target in the corner case where there are no analyzable columns.)
527
   */
528
0
  targrows = 100;
529
0
  for (i = 0; i < attr_cnt; i++)
530
0
  {
531
0
    if (targrows < vacattrstats[i]->minrows)
532
0
      targrows = vacattrstats[i]->minrows;
533
0
  }
534
0
  for (ind = 0; ind < nindexes; ind++)
535
0
  {
536
0
    AnlIndexData *thisdata = &indexdata[ind];
537
538
0
    for (i = 0; i < thisdata->attr_cnt; i++)
539
0
    {
540
0
      if (targrows < thisdata->vacattrstats[i]->minrows)
541
0
        targrows = thisdata->vacattrstats[i]->minrows;
542
0
    }
543
0
  }
544
545
  /*
546
   * Look at extended statistics objects too, as those may define custom
547
   * statistics target. So we may need to sample more rows and then build
548
   * the statistics with enough detail.
549
   */
550
0
  minrows = ComputeExtStatisticsRows(onerel, attr_cnt, vacattrstats);
551
552
0
  if (targrows < minrows)
553
0
    targrows = minrows;
554
555
  /*
556
   * Acquire the sample rows
557
   */
558
0
  rows = palloc_array(HeapTuple, targrows);
559
0
  pgstat_progress_update_param(PROGRESS_ANALYZE_PHASE,
560
0
                 inh ? PROGRESS_ANALYZE_PHASE_ACQUIRE_SAMPLE_ROWS_INH :
561
0
                 PROGRESS_ANALYZE_PHASE_ACQUIRE_SAMPLE_ROWS);
562
0
  if (inh)
563
0
    numrows = acquire_inherited_sample_rows(onerel, elevel,
564
0
                        rows, targrows,
565
0
                        &totalrows, &totaldeadrows);
566
0
  else
567
0
    numrows = (*acquirefunc) (onerel, elevel,
568
0
                  rows, targrows,
569
0
                  &totalrows, &totaldeadrows);
570
571
  /*
572
   * Compute the statistics.  Temporary results during the calculations for
573
   * each column are stored in a child context.  The calc routines are
574
   * responsible to make sure that whatever they store into the VacAttrStats
575
   * structure is allocated in anl_context.
576
   */
577
0
  if (numrows > 0)
578
0
  {
579
0
    MemoryContext col_context,
580
0
          old_context;
581
582
0
    pgstat_progress_update_param(PROGRESS_ANALYZE_PHASE,
583
0
                   PROGRESS_ANALYZE_PHASE_COMPUTE_STATS);
584
585
0
    col_context = AllocSetContextCreate(anl_context,
586
0
                      "Analyze Column",
587
0
                      ALLOCSET_DEFAULT_SIZES);
588
0
    old_context = MemoryContextSwitchTo(col_context);
589
590
0
    for (i = 0; i < attr_cnt; i++)
591
0
    {
592
0
      VacAttrStats *stats = vacattrstats[i];
593
0
      AttributeOpts *aopt;
594
595
0
      stats->rows = rows;
596
0
      stats->tupDesc = onerel->rd_att;
597
0
      stats->compute_stats(stats,
598
0
                 std_fetch_func,
599
0
                 numrows,
600
0
                 totalrows);
601
602
      /*
603
       * If the appropriate flavor of the n_distinct option is
604
       * specified, override with the corresponding value.
605
       */
606
0
      aopt = get_attribute_options(onerel->rd_id, stats->tupattnum);
607
0
      if (aopt != NULL)
608
0
      {
609
0
        float8    n_distinct;
610
611
0
        n_distinct = inh ? aopt->n_distinct_inherited : aopt->n_distinct;
612
0
        if (n_distinct != 0.0)
613
0
          stats->stadistinct = n_distinct;
614
0
      }
615
616
0
      MemoryContextReset(col_context);
617
0
    }
618
619
0
    if (nindexes > 0)
620
0
      compute_index_stats(onerel, totalrows,
621
0
                indexdata, nindexes,
622
0
                rows, numrows,
623
0
                col_context);
624
625
0
    MemoryContextSwitchTo(old_context);
626
0
    MemoryContextDelete(col_context);
627
628
    /*
629
     * Emit the completed stats rows into pg_statistic, replacing any
630
     * previous statistics for the target columns.  (If there are stats in
631
     * pg_statistic for columns we didn't process, we leave them alone.)
632
     */
633
0
    update_attstats(RelationGetRelid(onerel), inh,
634
0
            attr_cnt, vacattrstats);
635
636
0
    for (ind = 0; ind < nindexes; ind++)
637
0
    {
638
0
      AnlIndexData *thisdata = &indexdata[ind];
639
640
0
      update_attstats(RelationGetRelid(Irel[ind]), false,
641
0
              thisdata->attr_cnt, thisdata->vacattrstats);
642
0
    }
643
644
    /* Build extended statistics (if there are any). */
645
0
    BuildRelationExtStatistics(onerel, inh, totalrows, numrows, rows,
646
0
                   attr_cnt, vacattrstats);
647
0
  }
648
649
0
  pgstat_progress_update_param(PROGRESS_ANALYZE_PHASE,
650
0
                 PROGRESS_ANALYZE_PHASE_FINALIZE_ANALYZE);
651
652
  /*
653
   * Update pages/tuples stats in pg_class ... but not if we're doing
654
   * inherited stats.
655
   *
656
   * We assume that VACUUM hasn't set pg_class.reltuples already, even
657
   * during a VACUUM ANALYZE.  Although VACUUM often updates pg_class,
658
   * exceptions exist.  A "VACUUM (ANALYZE, INDEX_CLEANUP OFF)" command will
659
   * never update pg_class entries for index relations.  It's also possible
660
   * that an individual index's pg_class entry won't be updated during
661
   * VACUUM if the index AM returns NULL from its amvacuumcleanup() routine.
662
   */
663
0
  if (!inh)
664
0
  {
665
0
    BlockNumber relallvisible = 0;
666
0
    BlockNumber relallfrozen = 0;
667
668
0
    if (RELKIND_HAS_STORAGE(onerel->rd_rel->relkind))
669
0
      visibilitymap_count(onerel, &relallvisible, &relallfrozen);
670
671
    /*
672
     * Update pg_class for table relation.  CCI first, in case acquirefunc
673
     * updated pg_class.
674
     */
675
0
    CommandCounterIncrement();
676
0
    vac_update_relstats(onerel,
677
0
              relpages,
678
0
              totalrows,
679
0
              relallvisible,
680
0
              relallfrozen,
681
0
              hasindex,
682
0
              InvalidTransactionId,
683
0
              InvalidMultiXactId,
684
0
              NULL, NULL,
685
0
              in_outer_xact);
686
687
    /* Same for indexes */
688
0
    for (ind = 0; ind < nindexes; ind++)
689
0
    {
690
0
      AnlIndexData *thisdata = &indexdata[ind];
691
0
      double    totalindexrows;
692
693
0
      totalindexrows = ceil(thisdata->tupleFract * totalrows);
694
0
      vac_update_relstats(Irel[ind],
695
0
                RelationGetNumberOfBlocks(Irel[ind]),
696
0
                totalindexrows,
697
0
                0, 0,
698
0
                false,
699
0
                InvalidTransactionId,
700
0
                InvalidMultiXactId,
701
0
                NULL, NULL,
702
0
                in_outer_xact);
703
0
    }
704
0
  }
705
0
  else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
706
0
  {
707
    /*
708
     * Partitioned tables don't have storage, so we don't set any fields
709
     * in their pg_class entries except for reltuples and relhasindex.
710
     */
711
0
    CommandCounterIncrement();
712
0
    vac_update_relstats(onerel, -1, totalrows,
713
0
              0, 0, hasindex, InvalidTransactionId,
714
0
              InvalidMultiXactId,
715
0
              NULL, NULL,
716
0
              in_outer_xact);
717
0
  }
718
719
  /*
720
   * Now report ANALYZE to the cumulative stats system.  For regular tables,
721
   * we do it only if not doing inherited stats.  For partitioned tables, we
722
   * only do it for inherited stats. (We're never called for not-inherited
723
   * stats on partitioned tables anyway.)
724
   *
725
   * Reset the mod_since_analyze counter only if we analyzed all columns;
726
   * otherwise, there is still work for auto-analyze to do.
727
   */
728
0
  if (!inh)
729
0
    pgstat_report_analyze(onerel, totalrows, totaldeadrows,
730
0
                (va_cols == NIL), starttime);
731
0
  else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
732
0
    pgstat_report_analyze(onerel, 0, 0, (va_cols == NIL), starttime);
733
734
  /*
735
   * If this isn't part of VACUUM ANALYZE, let index AMs do cleanup.
736
   *
737
   * Note that most index AMs perform a no-op as a matter of policy for
738
   * amvacuumcleanup() when called in ANALYZE-only mode.  The only exception
739
   * among core index AMs is GIN/ginvacuumcleanup().
740
   */
741
0
  if (!(params->options & VACOPT_VACUUM))
742
0
  {
743
0
    for (ind = 0; ind < nindexes; ind++)
744
0
    {
745
0
      IndexBulkDeleteResult *stats;
746
0
      IndexVacuumInfo ivinfo;
747
748
0
      ivinfo.index = Irel[ind];
749
0
      ivinfo.heaprel = onerel;
750
0
      ivinfo.analyze_only = true;
751
0
      ivinfo.is_autovacuum = AmAutoVacuumWorkerProcess();
752
0
      ivinfo.estimated_count = true;
753
0
      ivinfo.message_level = elevel;
754
0
      ivinfo.num_heap_tuples = onerel->rd_rel->reltuples;
755
0
      ivinfo.strategy = vac_strategy;
756
757
0
      stats = index_vacuum_cleanup(&ivinfo, NULL);
758
759
0
      if (stats)
760
0
        pfree(stats);
761
0
    }
762
0
  }
763
764
  /* Done with indexes */
765
0
  vac_close_indexes(nindexes, Irel, NoLock);
766
767
  /* Log the action if appropriate */
768
0
  if (instrument)
769
0
  {
770
0
    TimestampTz endtime = GetCurrentTimestamp();
771
772
0
    if (verbose || params->log_analyze_min_duration == 0 ||
773
0
      TimestampDifferenceExceeds(starttime, endtime,
774
0
                     params->log_analyze_min_duration))
775
0
    {
776
0
      long    delay_in_ms;
777
0
      WalUsage  walusage;
778
0
      double    read_rate = 0;
779
0
      double    write_rate = 0;
780
0
      char     *msgfmt;
781
0
      StringInfoData buf;
782
0
      int64   total_blks_hit;
783
0
      int64   total_blks_read;
784
0
      int64   total_blks_dirtied;
785
786
0
      memset(&bufferusage, 0, sizeof(BufferUsage));
787
0
      BufferUsageAccumDiff(&bufferusage, &pgBufferUsage, &startbufferusage);
788
0
      memset(&walusage, 0, sizeof(WalUsage));
789
0
      WalUsageAccumDiff(&walusage, &pgWalUsage, &startwalusage);
790
791
0
      total_blks_hit = bufferusage.shared_blks_hit +
792
0
        bufferusage.local_blks_hit;
793
0
      total_blks_read = bufferusage.shared_blks_read +
794
0
        bufferusage.local_blks_read;
795
0
      total_blks_dirtied = bufferusage.shared_blks_dirtied +
796
0
        bufferusage.local_blks_dirtied;
797
798
      /*
799
       * We do not expect an analyze to take > 25 days and it simplifies
800
       * things a bit to use TimestampDifferenceMilliseconds.
801
       */
802
0
      delay_in_ms = TimestampDifferenceMilliseconds(starttime, endtime);
803
804
      /*
805
       * Note that we are reporting these read/write rates in the same
806
       * manner as VACUUM does, which means that while the 'average read
807
       * rate' here actually corresponds to page misses and resulting
808
       * reads which are also picked up by track_io_timing, if enabled,
809
       * the 'average write rate' is actually talking about the rate of
810
       * pages being dirtied, not being written out, so it's typical to
811
       * have a non-zero 'avg write rate' while I/O timings only reports
812
       * reads.
813
       *
814
       * It's not clear that an ANALYZE will ever result in
815
       * FlushBuffer() being called, but we track and support reporting
816
       * on I/O write time in case that changes as it's practically free
817
       * to do so anyway.
818
       */
819
820
0
      if (delay_in_ms > 0)
821
0
      {
822
0
        read_rate = (double) BLCKSZ * total_blks_read /
823
0
          (1024 * 1024) / (delay_in_ms / 1000.0);
824
0
        write_rate = (double) BLCKSZ * total_blks_dirtied /
825
0
          (1024 * 1024) / (delay_in_ms / 1000.0);
826
0
      }
827
828
      /*
829
       * We split this up so we don't emit empty I/O timing values when
830
       * track_io_timing isn't enabled.
831
       */
832
833
0
      initStringInfo(&buf);
834
835
0
      if (AmAutoVacuumWorkerProcess())
836
0
        msgfmt = _("automatic analyze of table \"%s.%s.%s\"\n");
837
0
      else
838
0
        msgfmt = _("finished analyzing table \"%s.%s.%s\"\n");
839
840
0
      appendStringInfo(&buf, msgfmt,
841
0
               get_database_name(MyDatabaseId),
842
0
               get_namespace_name(RelationGetNamespace(onerel)),
843
0
               RelationGetRelationName(onerel));
844
0
      if (track_cost_delay_timing)
845
0
      {
846
        /*
847
         * We bypass the changecount mechanism because this value is
848
         * only updated by the calling process.
849
         */
850
0
        appendStringInfo(&buf, _("delay time: %.3f ms\n"),
851
0
                 (double) MyBEEntry->st_progress_param[PROGRESS_ANALYZE_DELAY_TIME] / 1000000.0);
852
0
      }
853
0
      if (track_io_timing)
854
0
      {
855
0
        double    read_ms = (double) (pgStatBlockReadTime - startreadtime) / 1000;
856
0
        double    write_ms = (double) (pgStatBlockWriteTime - startwritetime) / 1000;
857
858
0
        appendStringInfo(&buf, _("I/O timings: read: %.3f ms, write: %.3f ms\n"),
859
0
                 read_ms, write_ms);
860
0
      }
861
0
      appendStringInfo(&buf, _("avg read rate: %.3f MB/s, avg write rate: %.3f MB/s\n"),
862
0
               read_rate, write_rate);
863
0
      appendStringInfo(&buf, _("buffer usage: %" PRId64 " hits, %" PRId64 " reads, %" PRId64 " dirtied\n"),
864
0
               total_blks_hit,
865
0
               total_blks_read,
866
0
               total_blks_dirtied);
867
0
      appendStringInfo(&buf,
868
0
               _("WAL usage: %" PRId64 " records, %" PRId64 " full page images, %" PRIu64 " bytes, %" PRIu64 " full page image bytes, %" PRId64 " buffers full\n"),
869
0
               walusage.wal_records,
870
0
               walusage.wal_fpi,
871
0
               walusage.wal_bytes,
872
0
               walusage.wal_fpi_bytes,
873
0
               walusage.wal_buffers_full);
874
0
      appendStringInfo(&buf, _("system usage: %s"), pg_rusage_show(&ru0));
875
876
0
      ereport(verbose ? INFO : LOG,
877
0
          (errmsg_internal("%s", buf.data)));
878
879
0
      pfree(buf.data);
880
0
    }
881
0
  }
882
883
  /* Roll back any GUC changes executed by index functions */
884
0
  AtEOXact_GUC(false, save_nestlevel);
885
886
  /* Restore userid and security context */
887
0
  SetUserIdAndSecContext(save_userid, save_sec_context);
888
889
  /* Restore current context and release memory */
890
0
  MemoryContextSwitchTo(caller_context);
891
0
  MemoryContextDelete(anl_context);
892
0
  anl_context = NULL;
893
0
}
894
895
/*
896
 * Compute statistics about indexes of a relation
897
 */
898
static void
899
compute_index_stats(Relation onerel, double totalrows,
900
          AnlIndexData *indexdata, int nindexes,
901
          HeapTuple *rows, int numrows,
902
          MemoryContext col_context)
903
0
{
904
0
  MemoryContext ind_context,
905
0
        old_context;
906
0
  Datum   values[INDEX_MAX_KEYS];
907
0
  bool    isnull[INDEX_MAX_KEYS];
908
0
  int     ind,
909
0
        i;
910
911
0
  ind_context = AllocSetContextCreate(anl_context,
912
0
                    "Analyze Index",
913
0
                    ALLOCSET_DEFAULT_SIZES);
914
0
  old_context = MemoryContextSwitchTo(ind_context);
915
916
0
  for (ind = 0; ind < nindexes; ind++)
917
0
  {
918
0
    AnlIndexData *thisdata = &indexdata[ind];
919
0
    IndexInfo  *indexInfo = thisdata->indexInfo;
920
0
    int     attr_cnt = thisdata->attr_cnt;
921
0
    TupleTableSlot *slot;
922
0
    EState     *estate;
923
0
    ExprContext *econtext;
924
0
    ExprState  *predicate;
925
0
    Datum    *exprvals;
926
0
    bool     *exprnulls;
927
0
    int     numindexrows,
928
0
          tcnt,
929
0
          rowno;
930
0
    double    totalindexrows;
931
932
    /* Ignore index if no columns to analyze and not partial */
933
0
    if (attr_cnt == 0 && indexInfo->ii_Predicate == NIL)
934
0
      continue;
935
936
    /*
937
     * Need an EState for evaluation of index expressions and
938
     * partial-index predicates.  Create it in the per-index context to be
939
     * sure it gets cleaned up at the bottom of the loop.
940
     */
941
0
    estate = CreateExecutorState();
942
0
    econtext = GetPerTupleExprContext(estate);
943
    /* Need a slot to hold the current heap tuple, too */
944
0
    slot = MakeSingleTupleTableSlot(RelationGetDescr(onerel),
945
0
                    &TTSOpsHeapTuple);
946
947
    /* Arrange for econtext's scan tuple to be the tuple under test */
948
0
    econtext->ecxt_scantuple = slot;
949
950
    /* Set up execution state for predicate. */
951
0
    predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
952
953
    /* Compute and save index expression values */
954
0
    exprvals = palloc_array(Datum, numrows * attr_cnt);
955
0
    exprnulls = palloc_array(bool, numrows * attr_cnt);
956
0
    numindexrows = 0;
957
0
    tcnt = 0;
958
0
    for (rowno = 0; rowno < numrows; rowno++)
959
0
    {
960
0
      HeapTuple heapTuple = rows[rowno];
961
962
0
      vacuum_delay_point(true);
963
964
      /*
965
       * Reset the per-tuple context each time, to reclaim any cruft
966
       * left behind by evaluating the predicate or index expressions.
967
       */
968
0
      ResetExprContext(econtext);
969
970
      /* Set up for predicate or expression evaluation */
971
0
      ExecStoreHeapTuple(heapTuple, slot, false);
972
973
      /* If index is partial, check predicate */
974
0
      if (predicate != NULL)
975
0
      {
976
0
        if (!ExecQual(predicate, econtext))
977
0
          continue;
978
0
      }
979
0
      numindexrows++;
980
981
0
      if (attr_cnt > 0)
982
0
      {
983
        /*
984
         * Evaluate the index row to compute expression values. We
985
         * could do this by hand, but FormIndexDatum is convenient.
986
         */
987
0
        FormIndexDatum(indexInfo,
988
0
                 slot,
989
0
                 estate,
990
0
                 values,
991
0
                 isnull);
992
993
        /*
994
         * Save just the columns we care about.  We copy the values
995
         * into ind_context from the estate's per-tuple context.
996
         */
997
0
        for (i = 0; i < attr_cnt; i++)
998
0
        {
999
0
          VacAttrStats *stats = thisdata->vacattrstats[i];
1000
0
          int     attnum = stats->tupattnum;
1001
1002
0
          if (isnull[attnum - 1])
1003
0
          {
1004
0
            exprvals[tcnt] = (Datum) 0;
1005
0
            exprnulls[tcnt] = true;
1006
0
          }
1007
0
          else
1008
0
          {
1009
0
            exprvals[tcnt] = datumCopy(values[attnum - 1],
1010
0
                           stats->attrtype->typbyval,
1011
0
                           stats->attrtype->typlen);
1012
0
            exprnulls[tcnt] = false;
1013
0
          }
1014
0
          tcnt++;
1015
0
        }
1016
0
      }
1017
0
    }
1018
1019
    /*
1020
     * Having counted the number of rows that pass the predicate in the
1021
     * sample, we can estimate the total number of rows in the index.
1022
     */
1023
0
    thisdata->tupleFract = (double) numindexrows / (double) numrows;
1024
0
    totalindexrows = ceil(thisdata->tupleFract * totalrows);
1025
1026
    /*
1027
     * Now we can compute the statistics for the expression columns.
1028
     */
1029
0
    if (numindexrows > 0)
1030
0
    {
1031
0
      MemoryContextSwitchTo(col_context);
1032
0
      for (i = 0; i < attr_cnt; i++)
1033
0
      {
1034
0
        VacAttrStats *stats = thisdata->vacattrstats[i];
1035
1036
0
        stats->exprvals = exprvals + i;
1037
0
        stats->exprnulls = exprnulls + i;
1038
0
        stats->rowstride = attr_cnt;
1039
0
        stats->compute_stats(stats,
1040
0
                   ind_fetch_func,
1041
0
                   numindexrows,
1042
0
                   totalindexrows);
1043
1044
0
        MemoryContextReset(col_context);
1045
0
      }
1046
0
    }
1047
1048
    /* And clean up */
1049
0
    MemoryContextSwitchTo(ind_context);
1050
1051
0
    ExecDropSingleTupleTableSlot(slot);
1052
0
    FreeExecutorState(estate);
1053
0
    MemoryContextReset(ind_context);
1054
0
  }
1055
1056
0
  MemoryContextSwitchTo(old_context);
1057
0
  MemoryContextDelete(ind_context);
1058
0
}
1059
1060
/*
1061
 * validate_va_cols_list -- validate the columns list given to analyze_rel
1062
 *
1063
 * Note that system attributes are never analyzed, so we just reject them at
1064
 * the lookup stage.  We also reject duplicate column mentions.  (We could
1065
 * alternatively ignore duplicates, but analyzing a column twice won't work;
1066
 * we'd end up making a conflicting update in pg_statistic.)
1067
 */
1068
static void
1069
validate_va_cols_list(Relation onerel, List *va_cols)
1070
0
{
1071
0
  Bitmapset  *unique_cols = NULL;
1072
0
  ListCell   *le;
1073
1074
0
  Assert(va_cols != NIL);
1075
0
  foreach(le, va_cols)
1076
0
  {
1077
0
    char     *col = strVal(lfirst(le));
1078
0
    int     i = attnameAttNum(onerel, col, false);
1079
1080
0
    if (i == InvalidAttrNumber)
1081
0
      ereport(ERROR,
1082
0
          (errcode(ERRCODE_UNDEFINED_COLUMN),
1083
0
           errmsg("column \"%s\" of relation \"%s\" does not exist",
1084
0
              col, RelationGetRelationName(onerel))));
1085
0
    if (bms_is_member(i, unique_cols))
1086
0
      ereport(ERROR,
1087
0
          (errcode(ERRCODE_DUPLICATE_COLUMN),
1088
0
           errmsg("column \"%s\" of relation \"%s\" appears more than once",
1089
0
              col, RelationGetRelationName(onerel))));
1090
0
    unique_cols = bms_add_member(unique_cols, i);
1091
0
  }
1092
0
}
1093
1094
/*
1095
 * examine_attribute -- pre-analysis of a single column
1096
 *
1097
 * Determine whether the column is analyzable; if so, create and initialize
1098
 * a VacAttrStats struct for it.  If not, return NULL.
1099
 *
1100
 * If index_expr isn't NULL, then we're trying to analyze an expression index,
1101
 * and index_expr is the expression tree representing the column's data.
1102
 */
1103
static VacAttrStats *
1104
examine_attribute(Relation onerel, int attnum, Node *index_expr)
1105
0
{
1106
0
  Form_pg_attribute attr = TupleDescAttr(onerel->rd_att, attnum - 1);
1107
0
  int     attstattarget;
1108
0
  HeapTuple typtuple;
1109
0
  VacAttrStats *stats;
1110
0
  int     i;
1111
0
  bool    ok;
1112
1113
  /*
1114
   * Check if the column is analyzable.
1115
   */
1116
0
  if (!attribute_is_analyzable(onerel, attnum, attr, &attstattarget))
1117
0
    return NULL;
1118
1119
  /*
1120
   * Create the VacAttrStats struct.
1121
   */
1122
0
  stats = palloc0_object(VacAttrStats);
1123
0
  stats->attstattarget = attstattarget;
1124
1125
  /*
1126
   * When analyzing an expression index, believe the expression tree's type
1127
   * not the column datatype --- the latter might be the opckeytype storage
1128
   * type of the opclass, which is not interesting for our purposes.  (Note:
1129
   * if we did anything with non-expression index columns, we'd need to
1130
   * figure out where to get the correct type info from, but for now that's
1131
   * not a problem.)  It's not clear whether anyone will care about the
1132
   * typmod, but we store that too just in case.
1133
   */
1134
0
  if (index_expr)
1135
0
  {
1136
0
    stats->attrtypid = exprType(index_expr);
1137
0
    stats->attrtypmod = exprTypmod(index_expr);
1138
1139
    /*
1140
     * If a collation has been specified for the index column, use that in
1141
     * preference to anything else; but if not, fall back to whatever we
1142
     * can get from the expression.
1143
     */
1144
0
    if (OidIsValid(onerel->rd_indcollation[attnum - 1]))
1145
0
      stats->attrcollid = onerel->rd_indcollation[attnum - 1];
1146
0
    else
1147
0
      stats->attrcollid = exprCollation(index_expr);
1148
0
  }
1149
0
  else
1150
0
  {
1151
0
    stats->attrtypid = attr->atttypid;
1152
0
    stats->attrtypmod = attr->atttypmod;
1153
0
    stats->attrcollid = attr->attcollation;
1154
0
  }
1155
1156
0
  typtuple = SearchSysCacheCopy1(TYPEOID,
1157
0
                   ObjectIdGetDatum(stats->attrtypid));
1158
0
  if (!HeapTupleIsValid(typtuple))
1159
0
    elog(ERROR, "cache lookup failed for type %u", stats->attrtypid);
1160
0
  stats->attrtype = (Form_pg_type) GETSTRUCT(typtuple);
1161
0
  stats->anl_context = anl_context;
1162
0
  stats->tupattnum = attnum;
1163
1164
  /*
1165
   * The fields describing the stats->stavalues[n] element types default to
1166
   * the type of the data being analyzed, but the type-specific typanalyze
1167
   * function can change them if it wants to store something else.
1168
   */
1169
0
  for (i = 0; i < STATISTIC_NUM_SLOTS; i++)
1170
0
  {
1171
0
    stats->statypid[i] = stats->attrtypid;
1172
0
    stats->statyplen[i] = stats->attrtype->typlen;
1173
0
    stats->statypbyval[i] = stats->attrtype->typbyval;
1174
0
    stats->statypalign[i] = stats->attrtype->typalign;
1175
0
  }
1176
1177
  /*
1178
   * Call the type-specific typanalyze function.  If none is specified, use
1179
   * std_typanalyze().
1180
   */
1181
0
  if (OidIsValid(stats->attrtype->typanalyze))
1182
0
    ok = DatumGetBool(OidFunctionCall1(stats->attrtype->typanalyze,
1183
0
                       PointerGetDatum(stats)));
1184
0
  else
1185
0
    ok = std_typanalyze(stats);
1186
1187
0
  if (!ok || stats->compute_stats == NULL || stats->minrows <= 0)
1188
0
  {
1189
0
    heap_freetuple(typtuple);
1190
0
    pfree(stats);
1191
0
    return NULL;
1192
0
  }
1193
1194
0
  return stats;
1195
0
}
1196
1197
/*
1198
 * Determine whether the column is analyzable.
1199
 *
1200
 * If the column is analyzable, return its attstattarget value, if asked to.
1201
 */
1202
bool
1203
attribute_is_analyzable(Relation onerel, int attnum, Form_pg_attribute attr,
1204
            int *p_attstattarget)
1205
0
{
1206
0
  int     attstattarget;
1207
0
  HeapTuple atttuple;
1208
0
  Datum   dat;
1209
0
  bool    isnull;
1210
1211
  /* Never analyze dropped columns */
1212
0
  if (attr->attisdropped)
1213
0
    return false;
1214
1215
  /* Don't analyze virtual generated columns */
1216
0
  if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
1217
0
    return false;
1218
1219
  /*
1220
   * Get attstattarget value.  Set to -1 if null.  (Analyze functions expect
1221
   * -1 to mean use default_statistics_target; see for example
1222
   * std_typanalyze.)
1223
   */
1224
0
  atttuple = SearchSysCache2(ATTNUM, ObjectIdGetDatum(RelationGetRelid(onerel)), Int16GetDatum(attnum));
1225
0
  if (!HeapTupleIsValid(atttuple))
1226
0
    elog(ERROR, "cache lookup failed for attribute %d of relation %u",
1227
0
       attnum, RelationGetRelid(onerel));
1228
0
  dat = SysCacheGetAttr(ATTNUM, atttuple, Anum_pg_attribute_attstattarget, &isnull);
1229
0
  attstattarget = isnull ? -1 : DatumGetInt16(dat);
1230
0
  ReleaseSysCache(atttuple);
1231
1232
  /* Don't analyze column if user has specified not to */
1233
0
  if (attstattarget == 0)
1234
0
    return false;
1235
1236
0
  if (p_attstattarget)
1237
0
    *p_attstattarget = attstattarget;
1238
0
  return true;
1239
0
}
1240
1241
/*
1242
 * Read stream callback returning the next BlockNumber as chosen by the
1243
 * BlockSampling algorithm.
1244
 */
1245
static BlockNumber
1246
block_sampling_read_stream_next(ReadStream *stream,
1247
                void *callback_private_data,
1248
                void *per_buffer_data)
1249
0
{
1250
0
  BlockSamplerData *bs = callback_private_data;
1251
1252
0
  return BlockSampler_HasMore(bs) ? BlockSampler_Next(bs) : InvalidBlockNumber;
1253
0
}
1254
1255
/*
1256
 * acquire_sample_rows -- acquire a random sample of rows from the table
1257
 *
1258
 * Selected rows are returned in the caller-allocated array rows[], which
1259
 * must have at least targrows entries.
1260
 * The actual number of rows selected is returned as the function result.
1261
 * We also estimate the total numbers of live and dead rows in the table,
1262
 * and return them into *totalrows and *totaldeadrows, respectively.
1263
 *
1264
 * The returned list of tuples is in order by physical position in the table.
1265
 * (We will rely on this later to derive correlation estimates.)
1266
 *
1267
 * As of May 2004 we use a new two-stage method:  Stage one selects up
1268
 * to targrows random blocks (or all blocks, if there aren't so many).
1269
 * Stage two scans these blocks and uses the Vitter algorithm to create
1270
 * a random sample of targrows rows (or less, if there are less in the
1271
 * sample of blocks).  The two stages are executed simultaneously: each
1272
 * block is processed as soon as stage one returns its number and while
1273
 * the rows are read stage two controls which ones are to be inserted
1274
 * into the sample.
1275
 *
1276
 * Although every row has an equal chance of ending up in the final
1277
 * sample, this sampling method is not perfect: not every possible
1278
 * sample has an equal chance of being selected.  For large relations
1279
 * the number of different blocks represented by the sample tends to be
1280
 * too small.  We can live with that for now.  Improvements are welcome.
1281
 *
1282
 * An important property of this sampling method is that because we do
1283
 * look at a statistically unbiased set of blocks, we should get
1284
 * unbiased estimates of the average numbers of live and dead rows per
1285
 * block.  The previous sampling method put too much credence in the row
1286
 * density near the start of the table.
1287
 */
1288
static int
1289
acquire_sample_rows(Relation onerel, int elevel,
1290
          HeapTuple *rows, int targrows,
1291
          double *totalrows, double *totaldeadrows)
1292
0
{
1293
0
  int     numrows = 0;  /* # rows now in reservoir */
1294
0
  double    samplerows = 0; /* total # rows collected */
1295
0
  double    liverows = 0; /* # live rows seen */
1296
0
  double    deadrows = 0; /* # dead rows seen */
1297
0
  double    rowstoskip = -1;  /* -1 means not set yet */
1298
0
  uint32    randseed;   /* Seed for block sampler(s) */
1299
0
  BlockNumber totalblocks;
1300
0
  BlockSamplerData bs;
1301
0
  ReservoirStateData rstate;
1302
0
  TupleTableSlot *slot;
1303
0
  TableScanDesc scan;
1304
0
  BlockNumber nblocks;
1305
0
  BlockNumber blksdone = 0;
1306
0
  ReadStream *stream;
1307
1308
0
  Assert(targrows > 0);
1309
1310
0
  totalblocks = RelationGetNumberOfBlocks(onerel);
1311
1312
  /* Prepare for sampling block numbers */
1313
0
  randseed = pg_prng_uint32(&pg_global_prng_state);
1314
0
  nblocks = BlockSampler_Init(&bs, totalblocks, targrows, randseed);
1315
1316
  /* Report sampling block numbers */
1317
0
  pgstat_progress_update_param(PROGRESS_ANALYZE_BLOCKS_TOTAL,
1318
0
                 nblocks);
1319
1320
  /* Prepare for sampling rows */
1321
0
  reservoir_init_selection_state(&rstate, targrows);
1322
1323
0
  scan = table_beginscan_analyze(onerel);
1324
0
  slot = table_slot_create(onerel, NULL);
1325
1326
  /*
1327
   * It is safe to use batching, as block_sampling_read_stream_next never
1328
   * blocks.
1329
   */
1330
0
  stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE |
1331
0
                    READ_STREAM_USE_BATCHING,
1332
0
                    vac_strategy,
1333
0
                    scan->rs_rd,
1334
0
                    MAIN_FORKNUM,
1335
0
                    block_sampling_read_stream_next,
1336
0
                    &bs,
1337
0
                    0);
1338
1339
  /* Outer loop over blocks to sample */
1340
0
  while (table_scan_analyze_next_block(scan, stream))
1341
0
  {
1342
0
    while (table_scan_analyze_next_tuple(scan, &liverows, &deadrows, slot))
1343
0
    {
1344
      /*
1345
       * The first targrows sample rows are simply copied into the
1346
       * reservoir. Then we start replacing tuples in the sample until
1347
       * we reach the end of the relation.  This algorithm is from Jeff
1348
       * Vitter's paper (see full citation in utils/misc/sampling.c). It
1349
       * works by repeatedly computing the number of tuples to skip
1350
       * before selecting a tuple, which replaces a randomly chosen
1351
       * element of the reservoir (current set of tuples).  At all times
1352
       * the reservoir is a true random sample of the tuples we've
1353
       * passed over so far, so when we fall off the end of the relation
1354
       * we're done.
1355
       */
1356
0
      if (numrows < targrows)
1357
0
        rows[numrows++] = ExecCopySlotHeapTuple(slot);
1358
0
      else
1359
0
      {
1360
        /*
1361
         * t in Vitter's paper is the number of records already
1362
         * processed.  If we need to compute a new S value, we must
1363
         * use the not-yet-incremented value of samplerows as t.
1364
         */
1365
0
        if (rowstoskip < 0)
1366
0
          rowstoskip = reservoir_get_next_S(&rstate, samplerows, targrows);
1367
1368
0
        if (rowstoskip <= 0)
1369
0
        {
1370
          /*
1371
           * Found a suitable tuple, so save it, replacing one old
1372
           * tuple at random
1373
           */
1374
0
          int     k = (int) (targrows * sampler_random_fract(&rstate.randstate));
1375
1376
0
          Assert(k >= 0 && k < targrows);
1377
0
          heap_freetuple(rows[k]);
1378
0
          rows[k] = ExecCopySlotHeapTuple(slot);
1379
0
        }
1380
1381
0
        rowstoskip -= 1;
1382
0
      }
1383
1384
0
      samplerows += 1;
1385
0
    }
1386
1387
0
    pgstat_progress_update_param(PROGRESS_ANALYZE_BLOCKS_DONE,
1388
0
                   ++blksdone);
1389
0
    vacuum_delay_point(true);
1390
0
  }
1391
1392
0
  read_stream_end(stream);
1393
1394
0
  ExecDropSingleTupleTableSlot(slot);
1395
0
  table_endscan(scan);
1396
1397
  /*
1398
   * If we didn't find as many tuples as we wanted then we're done. No sort
1399
   * is needed, since they're already in order.
1400
   *
1401
   * Otherwise we need to sort the collected tuples by position
1402
   * (itempointer). It's not worth worrying about corner cases where the
1403
   * tuples are already sorted.
1404
   */
1405
0
  if (numrows == targrows)
1406
0
    qsort_interruptible(rows, numrows, sizeof(HeapTuple),
1407
0
              compare_rows, NULL);
1408
1409
  /*
1410
   * Estimate total numbers of live and dead rows in relation, extrapolating
1411
   * on the assumption that the average tuple density in pages we didn't
1412
   * scan is the same as in the pages we did scan.  Since what we scanned is
1413
   * a random sample of the pages in the relation, this should be a good
1414
   * assumption.
1415
   */
1416
0
  if (bs.m > 0)
1417
0
  {
1418
0
    *totalrows = floor((liverows / bs.m) * totalblocks + 0.5);
1419
0
    *totaldeadrows = floor((deadrows / bs.m) * totalblocks + 0.5);
1420
0
  }
1421
0
  else
1422
0
  {
1423
0
    *totalrows = 0.0;
1424
0
    *totaldeadrows = 0.0;
1425
0
  }
1426
1427
  /*
1428
   * Emit some interesting relation info
1429
   */
1430
0
  ereport(elevel,
1431
0
      (errmsg("\"%s\": scanned %d of %u pages, "
1432
0
          "containing %.0f live rows and %.0f dead rows; "
1433
0
          "%d rows in sample, %.0f estimated total rows",
1434
0
          RelationGetRelationName(onerel),
1435
0
          bs.m, totalblocks,
1436
0
          liverows, deadrows,
1437
0
          numrows, *totalrows)));
1438
1439
0
  return numrows;
1440
0
}
1441
1442
/*
1443
 * Comparator for sorting rows[] array
1444
 */
1445
static int
1446
compare_rows(const void *a, const void *b, void *arg)
1447
0
{
1448
0
  HeapTuple ha = *(const HeapTuple *) a;
1449
0
  HeapTuple hb = *(const HeapTuple *) b;
1450
0
  BlockNumber ba = ItemPointerGetBlockNumber(&ha->t_self);
1451
0
  OffsetNumber oa = ItemPointerGetOffsetNumber(&ha->t_self);
1452
0
  BlockNumber bb = ItemPointerGetBlockNumber(&hb->t_self);
1453
0
  OffsetNumber ob = ItemPointerGetOffsetNumber(&hb->t_self);
1454
1455
0
  if (ba < bb)
1456
0
    return -1;
1457
0
  if (ba > bb)
1458
0
    return 1;
1459
0
  if (oa < ob)
1460
0
    return -1;
1461
0
  if (oa > ob)
1462
0
    return 1;
1463
0
  return 0;
1464
0
}
1465
1466
1467
/*
1468
 * acquire_inherited_sample_rows -- acquire sample rows from inheritance tree
1469
 *
1470
 * This has the same API as acquire_sample_rows, except that rows are
1471
 * collected from all inheritance children as well as the specified table.
1472
 * We fail and return zero if there are no inheritance children, or if all
1473
 * children are foreign tables that don't support ANALYZE.
1474
 */
1475
static int
1476
acquire_inherited_sample_rows(Relation onerel, int elevel,
1477
                HeapTuple *rows, int targrows,
1478
                double *totalrows, double *totaldeadrows)
1479
0
{
1480
0
  List     *tableOIDs;
1481
0
  Relation   *rels;
1482
0
  AcquireSampleRowsFunc *acquirefuncs;
1483
0
  double     *relblocks;
1484
0
  double    totalblocks;
1485
0
  int     numrows,
1486
0
        nrels,
1487
0
        i;
1488
0
  ListCell   *lc;
1489
0
  bool    has_child;
1490
1491
  /* Initialize output parameters to zero now, in case we exit early */
1492
0
  *totalrows = 0;
1493
0
  *totaldeadrows = 0;
1494
1495
  /*
1496
   * Find all members of inheritance set.  We only need AccessShareLock on
1497
   * the children.
1498
   */
1499
0
  tableOIDs =
1500
0
    find_all_inheritors(RelationGetRelid(onerel), AccessShareLock, NULL);
1501
1502
  /*
1503
   * Check that there's at least one descendant, else fail.  This could
1504
   * happen despite analyze_rel's relhassubclass check, if table once had a
1505
   * child but no longer does.  In that case, we can clear the
1506
   * relhassubclass field so as not to make the same mistake again later.
1507
   * (This is safe because we hold ShareUpdateExclusiveLock.)
1508
   */
1509
0
  if (list_length(tableOIDs) < 2)
1510
0
  {
1511
    /* CCI because we already updated the pg_class row in this command */
1512
0
    CommandCounterIncrement();
1513
0
    SetRelationHasSubclass(RelationGetRelid(onerel), false);
1514
0
    ereport(elevel,
1515
0
        (errmsg("skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no child tables",
1516
0
            get_namespace_name(RelationGetNamespace(onerel)),
1517
0
            RelationGetRelationName(onerel))));
1518
0
    return 0;
1519
0
  }
1520
1521
  /*
1522
   * Identify acquirefuncs to use, and count blocks in all the relations.
1523
   * The result could overflow BlockNumber, so we use double arithmetic.
1524
   */
1525
0
  rels = palloc_array(Relation, list_length(tableOIDs));
1526
0
  acquirefuncs = palloc_array(AcquireSampleRowsFunc, list_length(tableOIDs));
1527
0
  relblocks = palloc_array(double, list_length(tableOIDs));
1528
0
  totalblocks = 0;
1529
0
  nrels = 0;
1530
0
  has_child = false;
1531
0
  foreach(lc, tableOIDs)
1532
0
  {
1533
0
    Oid     childOID = lfirst_oid(lc);
1534
0
    Relation  childrel;
1535
0
    AcquireSampleRowsFunc acquirefunc = NULL;
1536
0
    BlockNumber relpages = 0;
1537
1538
    /* We already got the needed lock */
1539
0
    childrel = table_open(childOID, NoLock);
1540
1541
    /* Ignore if temp table of another backend */
1542
0
    if (RELATION_IS_OTHER_TEMP(childrel))
1543
0
    {
1544
      /* ... but release the lock on it */
1545
0
      Assert(childrel != onerel);
1546
0
      table_close(childrel, AccessShareLock);
1547
0
      continue;
1548
0
    }
1549
1550
    /* Check table type (MATVIEW can't happen, but might as well allow) */
1551
0
    if (childrel->rd_rel->relkind == RELKIND_RELATION ||
1552
0
      childrel->rd_rel->relkind == RELKIND_MATVIEW)
1553
0
    {
1554
      /* Regular table, so use the regular row acquisition function */
1555
0
      acquirefunc = acquire_sample_rows;
1556
0
      relpages = RelationGetNumberOfBlocks(childrel);
1557
0
    }
1558
0
    else if (childrel->rd_rel->relkind == RELKIND_FOREIGN_TABLE)
1559
0
    {
1560
      /*
1561
       * For a foreign table, call the FDW's hook function to see
1562
       * whether it supports analysis.
1563
       */
1564
0
      FdwRoutine *fdwroutine;
1565
0
      bool    ok = false;
1566
1567
0
      fdwroutine = GetFdwRoutineForRelation(childrel, false);
1568
1569
0
      if (fdwroutine->AnalyzeForeignTable != NULL)
1570
0
        ok = fdwroutine->AnalyzeForeignTable(childrel,
1571
0
                           &acquirefunc,
1572
0
                           &relpages);
1573
1574
0
      if (!ok)
1575
0
      {
1576
        /* ignore, but release the lock on it */
1577
0
        Assert(childrel != onerel);
1578
0
        table_close(childrel, AccessShareLock);
1579
0
        continue;
1580
0
      }
1581
0
    }
1582
0
    else
1583
0
    {
1584
      /*
1585
       * ignore, but release the lock on it.  don't try to unlock the
1586
       * passed-in relation
1587
       */
1588
0
      Assert(childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE);
1589
0
      if (childrel != onerel)
1590
0
        table_close(childrel, AccessShareLock);
1591
0
      else
1592
0
        table_close(childrel, NoLock);
1593
0
      continue;
1594
0
    }
1595
1596
    /* OK, we'll process this child */
1597
0
    has_child = true;
1598
0
    rels[nrels] = childrel;
1599
0
    acquirefuncs[nrels] = acquirefunc;
1600
0
    relblocks[nrels] = (double) relpages;
1601
0
    totalblocks += (double) relpages;
1602
0
    nrels++;
1603
0
  }
1604
1605
  /*
1606
   * If we don't have at least one child table to consider, fail.  If the
1607
   * relation is a partitioned table, it's not counted as a child table.
1608
   */
1609
0
  if (!has_child)
1610
0
  {
1611
0
    ereport(elevel,
1612
0
        (errmsg("skipping analyze of \"%s.%s\" inheritance tree --- this inheritance tree contains no analyzable child tables",
1613
0
            get_namespace_name(RelationGetNamespace(onerel)),
1614
0
            RelationGetRelationName(onerel))));
1615
0
    return 0;
1616
0
  }
1617
1618
  /*
1619
   * Now sample rows from each relation, proportionally to its fraction of
1620
   * the total block count.  (This might be less than desirable if the child
1621
   * rels have radically different free-space percentages, but it's not
1622
   * clear that it's worth working harder.)
1623
   */
1624
0
  pgstat_progress_update_param(PROGRESS_ANALYZE_CHILD_TABLES_TOTAL,
1625
0
                 nrels);
1626
0
  numrows = 0;
1627
0
  for (i = 0; i < nrels; i++)
1628
0
  {
1629
0
    Relation  childrel = rels[i];
1630
0
    AcquireSampleRowsFunc acquirefunc = acquirefuncs[i];
1631
0
    double    childblocks = relblocks[i];
1632
1633
    /*
1634
     * Report progress.  The sampling function will normally report blocks
1635
     * done/total, but we need to reset them to 0 here, so that they don't
1636
     * show an old value until that.
1637
     */
1638
0
    {
1639
0
      const int progress_index[] = {
1640
0
        PROGRESS_ANALYZE_CURRENT_CHILD_TABLE_RELID,
1641
0
        PROGRESS_ANALYZE_BLOCKS_DONE,
1642
0
        PROGRESS_ANALYZE_BLOCKS_TOTAL
1643
0
      };
1644
0
      const int64 progress_vals[] = {
1645
0
        RelationGetRelid(childrel),
1646
0
        0,
1647
0
        0,
1648
0
      };
1649
1650
0
      pgstat_progress_update_multi_param(3, progress_index, progress_vals);
1651
0
    }
1652
1653
0
    if (childblocks > 0)
1654
0
    {
1655
0
      int     childtargrows;
1656
1657
0
      childtargrows = (int) rint(targrows * childblocks / totalblocks);
1658
      /* Make sure we don't overrun due to roundoff error */
1659
0
      childtargrows = Min(childtargrows, targrows - numrows);
1660
0
      if (childtargrows > 0)
1661
0
      {
1662
0
        int     childrows;
1663
0
        double    trows,
1664
0
              tdrows;
1665
1666
        /* Fetch a random sample of the child's rows */
1667
0
        childrows = (*acquirefunc) (childrel, elevel,
1668
0
                      rows + numrows, childtargrows,
1669
0
                      &trows, &tdrows);
1670
1671
        /* We may need to convert from child's rowtype to parent's */
1672
0
        if (childrows > 0 &&
1673
0
          !equalRowTypes(RelationGetDescr(childrel),
1674
0
                   RelationGetDescr(onerel)))
1675
0
        {
1676
0
          TupleConversionMap *map;
1677
1678
0
          map = convert_tuples_by_name(RelationGetDescr(childrel),
1679
0
                         RelationGetDescr(onerel));
1680
0
          if (map != NULL)
1681
0
          {
1682
0
            int     j;
1683
1684
0
            for (j = 0; j < childrows; j++)
1685
0
            {
1686
0
              HeapTuple newtup;
1687
1688
0
              newtup = execute_attr_map_tuple(rows[numrows + j], map);
1689
0
              heap_freetuple(rows[numrows + j]);
1690
0
              rows[numrows + j] = newtup;
1691
0
            }
1692
0
            free_conversion_map(map);
1693
0
          }
1694
0
        }
1695
1696
        /* And add to counts */
1697
0
        numrows += childrows;
1698
0
        *totalrows += trows;
1699
0
        *totaldeadrows += tdrows;
1700
0
      }
1701
0
    }
1702
1703
    /*
1704
     * Note: we cannot release the child-table locks, since we may have
1705
     * pointers to their TOAST tables in the sampled rows.
1706
     */
1707
0
    table_close(childrel, NoLock);
1708
0
    pgstat_progress_update_param(PROGRESS_ANALYZE_CHILD_TABLES_DONE,
1709
0
                   i + 1);
1710
0
  }
1711
1712
0
  return numrows;
1713
0
}
1714
1715
1716
/*
1717
 *  update_attstats() -- update attribute statistics for one relation
1718
 *
1719
 *    Statistics are stored in several places: the pg_class row for the
1720
 *    relation has stats about the whole relation, and there is a
1721
 *    pg_statistic row for each (non-system) attribute that has ever
1722
 *    been analyzed.  The pg_class values are updated by VACUUM, not here.
1723
 *
1724
 *    pg_statistic rows are just added or updated normally.  This means
1725
 *    that pg_statistic will probably contain some deleted rows at the
1726
 *    completion of a vacuum cycle, unless it happens to get vacuumed last.
1727
 *
1728
 *    To keep things simple, we punt for pg_statistic, and don't try
1729
 *    to compute or store rows for pg_statistic itself in pg_statistic.
1730
 *    This could possibly be made to work, but it's not worth the trouble.
1731
 *    Note analyze_rel() has seen to it that we won't come here when
1732
 *    vacuuming pg_statistic itself.
1733
 *
1734
 *    Note: there would be a race condition here if two backends could
1735
 *    ANALYZE the same table concurrently.  Presently, we lock that out
1736
 *    by taking a self-exclusive lock on the relation in analyze_rel().
1737
 */
1738
static void
1739
update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
1740
0
{
1741
0
  Relation  sd;
1742
0
  int     attno;
1743
0
  CatalogIndexState indstate = NULL;
1744
1745
0
  if (natts <= 0)
1746
0
    return;         /* nothing to do */
1747
1748
0
  sd = table_open(StatisticRelationId, RowExclusiveLock);
1749
1750
0
  for (attno = 0; attno < natts; attno++)
1751
0
  {
1752
0
    VacAttrStats *stats = vacattrstats[attno];
1753
0
    HeapTuple stup,
1754
0
          oldtup;
1755
0
    int     i,
1756
0
          k,
1757
0
          n;
1758
0
    Datum   values[Natts_pg_statistic];
1759
0
    bool    nulls[Natts_pg_statistic];
1760
0
    bool    replaces[Natts_pg_statistic];
1761
1762
    /* Ignore attr if we weren't able to collect stats */
1763
0
    if (!stats->stats_valid)
1764
0
      continue;
1765
1766
    /*
1767
     * Construct a new pg_statistic tuple
1768
     */
1769
0
    for (i = 0; i < Natts_pg_statistic; ++i)
1770
0
    {
1771
0
      nulls[i] = false;
1772
0
      replaces[i] = true;
1773
0
    }
1774
1775
0
    values[Anum_pg_statistic_starelid - 1] = ObjectIdGetDatum(relid);
1776
0
    values[Anum_pg_statistic_staattnum - 1] = Int16GetDatum(stats->tupattnum);
1777
0
    values[Anum_pg_statistic_stainherit - 1] = BoolGetDatum(inh);
1778
0
    values[Anum_pg_statistic_stanullfrac - 1] = Float4GetDatum(stats->stanullfrac);
1779
0
    values[Anum_pg_statistic_stawidth - 1] = Int32GetDatum(stats->stawidth);
1780
0
    values[Anum_pg_statistic_stadistinct - 1] = Float4GetDatum(stats->stadistinct);
1781
0
    i = Anum_pg_statistic_stakind1 - 1;
1782
0
    for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
1783
0
    {
1784
0
      values[i++] = Int16GetDatum(stats->stakind[k]); /* stakindN */
1785
0
    }
1786
0
    i = Anum_pg_statistic_staop1 - 1;
1787
0
    for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
1788
0
    {
1789
0
      values[i++] = ObjectIdGetDatum(stats->staop[k]);  /* staopN */
1790
0
    }
1791
0
    i = Anum_pg_statistic_stacoll1 - 1;
1792
0
    for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
1793
0
    {
1794
0
      values[i++] = ObjectIdGetDatum(stats->stacoll[k]);  /* stacollN */
1795
0
    }
1796
0
    i = Anum_pg_statistic_stanumbers1 - 1;
1797
0
    for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
1798
0
    {
1799
0
      if (stats->stanumbers[k] != NULL)
1800
0
      {
1801
0
        int     nnum = stats->numnumbers[k];
1802
0
        Datum    *numdatums = palloc_array(Datum, nnum);
1803
0
        ArrayType  *arry;
1804
1805
0
        for (n = 0; n < nnum; n++)
1806
0
          numdatums[n] = Float4GetDatum(stats->stanumbers[k][n]);
1807
0
        arry = construct_array_builtin(numdatums, nnum, FLOAT4OID);
1808
0
        values[i++] = PointerGetDatum(arry); /* stanumbersN */
1809
0
      }
1810
0
      else
1811
0
      {
1812
0
        nulls[i] = true;
1813
0
        values[i++] = (Datum) 0;
1814
0
      }
1815
0
    }
1816
0
    i = Anum_pg_statistic_stavalues1 - 1;
1817
0
    for (k = 0; k < STATISTIC_NUM_SLOTS; k++)
1818
0
    {
1819
0
      if (stats->stavalues[k] != NULL)
1820
0
      {
1821
0
        ArrayType  *arry;
1822
1823
0
        arry = construct_array(stats->stavalues[k],
1824
0
                     stats->numvalues[k],
1825
0
                     stats->statypid[k],
1826
0
                     stats->statyplen[k],
1827
0
                     stats->statypbyval[k],
1828
0
                     stats->statypalign[k]);
1829
0
        values[i++] = PointerGetDatum(arry); /* stavaluesN */
1830
0
      }
1831
0
      else
1832
0
      {
1833
0
        nulls[i] = true;
1834
0
        values[i++] = (Datum) 0;
1835
0
      }
1836
0
    }
1837
1838
    /* Is there already a pg_statistic tuple for this attribute? */
1839
0
    oldtup = SearchSysCache3(STATRELATTINH,
1840
0
                 ObjectIdGetDatum(relid),
1841
0
                 Int16GetDatum(stats->tupattnum),
1842
0
                 BoolGetDatum(inh));
1843
1844
    /* Open index information when we know we need it */
1845
0
    if (indstate == NULL)
1846
0
      indstate = CatalogOpenIndexes(sd);
1847
1848
0
    if (HeapTupleIsValid(oldtup))
1849
0
    {
1850
      /* Yes, replace it */
1851
0
      stup = heap_modify_tuple(oldtup,
1852
0
                   RelationGetDescr(sd),
1853
0
                   values,
1854
0
                   nulls,
1855
0
                   replaces);
1856
0
      ReleaseSysCache(oldtup);
1857
0
      CatalogTupleUpdateWithInfo(sd, &stup->t_self, stup, indstate);
1858
0
    }
1859
0
    else
1860
0
    {
1861
      /* No, insert new tuple */
1862
0
      stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
1863
0
      CatalogTupleInsertWithInfo(sd, stup, indstate);
1864
0
    }
1865
1866
0
    heap_freetuple(stup);
1867
0
  }
1868
1869
0
  if (indstate != NULL)
1870
0
    CatalogCloseIndexes(indstate);
1871
0
  table_close(sd, RowExclusiveLock);
1872
0
}
1873
1874
/*
1875
 * Standard fetch function for use by compute_stats subroutines.
1876
 *
1877
 * This exists to provide some insulation between compute_stats routines
1878
 * and the actual storage of the sample data.
1879
 */
1880
static Datum
1881
std_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull)
1882
0
{
1883
0
  int     attnum = stats->tupattnum;
1884
0
  HeapTuple tuple = stats->rows[rownum];
1885
0
  TupleDesc tupDesc = stats->tupDesc;
1886
1887
0
  return heap_getattr(tuple, attnum, tupDesc, isNull);
1888
0
}
1889
1890
/*
1891
 * Fetch function for analyzing index expressions.
1892
 *
1893
 * We have not bothered to construct index tuples, instead the data is
1894
 * just in Datum arrays.
1895
 */
1896
static Datum
1897
ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull)
1898
0
{
1899
0
  int     i;
1900
1901
  /* exprvals and exprnulls are already offset for proper column */
1902
0
  i = rownum * stats->rowstride;
1903
0
  *isNull = stats->exprnulls[i];
1904
0
  return stats->exprvals[i];
1905
0
}
1906
1907
1908
/*
1909
 * ==========================================================================
1910
 *
1911
 * Code below this point represents the "standard" type-specific statistics
1912
 * analysis algorithms.  This code can be replaced on a per-data-type basis
1913
 * by setting a nonzero value in pg_type.typanalyze.
1914
 *
1915
 *==========================================================================
1916
 */
1917
1918
1919
/*
1920
 * To avoid consuming too much memory during analysis and/or too much space
1921
 * in the resulting pg_statistic rows, we ignore varlena datums that are wider
1922
 * than WIDTH_THRESHOLD (after detoasting!).  This is legitimate for MCV
1923
 * and distinct-value calculations since a wide value is unlikely to be
1924
 * duplicated at all, much less be a most-common value.  For the same reason,
1925
 * ignoring wide values will not affect our estimates of histogram bin
1926
 * boundaries very much.
1927
 */
1928
0
#define WIDTH_THRESHOLD  1024
1929
1930
0
#define swapInt(a,b)  do {int _tmp; _tmp=a; a=b; b=_tmp;} while(0)
1931
0
#define swapDatum(a,b)  do {Datum _tmp; _tmp=a; a=b; b=_tmp;} while(0)
1932
1933
/*
1934
 * Extra information used by the default analysis routines
1935
 */
1936
typedef struct
1937
{
1938
  int     count;      /* # of duplicates */
1939
  int     first;      /* values[] index of first occurrence */
1940
} ScalarMCVItem;
1941
1942
typedef struct
1943
{
1944
  SortSupport ssup;
1945
  int      *tupnoLink;
1946
} CompareScalarsContext;
1947
1948
1949
static void compute_trivial_stats(VacAttrStatsP stats,
1950
                  AnalyzeAttrFetchFunc fetchfunc,
1951
                  int samplerows,
1952
                  double totalrows);
1953
static void compute_distinct_stats(VacAttrStatsP stats,
1954
                   AnalyzeAttrFetchFunc fetchfunc,
1955
                   int samplerows,
1956
                   double totalrows);
1957
static void compute_scalar_stats(VacAttrStatsP stats,
1958
                 AnalyzeAttrFetchFunc fetchfunc,
1959
                 int samplerows,
1960
                 double totalrows);
1961
static int  compare_scalars(const void *a, const void *b, void *arg);
1962
static int  compare_mcvs(const void *a, const void *b, void *arg);
1963
static int  analyze_mcv_list(int *mcv_counts,
1964
               int num_mcv,
1965
               double stadistinct,
1966
               double stanullfrac,
1967
               int samplerows,
1968
               double totalrows);
1969
1970
1971
/*
1972
 * std_typanalyze -- the default type-specific typanalyze function
1973
 */
1974
bool
1975
std_typanalyze(VacAttrStats *stats)
1976
0
{
1977
0
  Oid     ltopr;
1978
0
  Oid     eqopr;
1979
0
  StdAnalyzeData *mystats;
1980
1981
  /* If the attstattarget column is negative, use the default value */
1982
0
  if (stats->attstattarget < 0)
1983
0
    stats->attstattarget = default_statistics_target;
1984
1985
  /* Look for default "<" and "=" operators for column's type */
1986
0
  get_sort_group_operators(stats->attrtypid,
1987
0
               false, false, false,
1988
0
               &ltopr, &eqopr, NULL,
1989
0
               NULL);
1990
1991
  /* Save the operator info for compute_stats routines */
1992
0
  mystats = palloc_object(StdAnalyzeData);
1993
0
  mystats->eqopr = eqopr;
1994
0
  mystats->eqfunc = OidIsValid(eqopr) ? get_opcode(eqopr) : InvalidOid;
1995
0
  mystats->ltopr = ltopr;
1996
0
  stats->extra_data = mystats;
1997
1998
  /*
1999
   * Determine which standard statistics algorithm to use
2000
   */
2001
0
  if (OidIsValid(eqopr) && OidIsValid(ltopr))
2002
0
  {
2003
    /* Seems to be a scalar datatype */
2004
0
    stats->compute_stats = compute_scalar_stats;
2005
    /*--------------------
2006
     * The following choice of minrows is based on the paper
2007
     * "Random sampling for histogram construction: how much is enough?"
2008
     * by Surajit Chaudhuri, Rajeev Motwani and Vivek Narasayya, in
2009
     * Proceedings of ACM SIGMOD International Conference on Management
2010
     * of Data, 1998, Pages 436-447.  Their Corollary 1 to Theorem 5
2011
     * says that for table size n, histogram size k, maximum relative
2012
     * error in bin size f, and error probability gamma, the minimum
2013
     * random sample size is
2014
     *    r = 4 * k * ln(2*n/gamma) / f^2
2015
     * Taking f = 0.5, gamma = 0.01, n = 10^6 rows, we obtain
2016
     *    r = 305.82 * k
2017
     * Note that because of the log function, the dependence on n is
2018
     * quite weak; even at n = 10^12, a 300*k sample gives <= 0.66
2019
     * bin size error with probability 0.99.  So there's no real need to
2020
     * scale for n, which is a good thing because we don't necessarily
2021
     * know it at this point.
2022
     *--------------------
2023
     */
2024
0
    stats->minrows = 300 * stats->attstattarget;
2025
0
  }
2026
0
  else if (OidIsValid(eqopr))
2027
0
  {
2028
    /* We can still recognize distinct values */
2029
0
    stats->compute_stats = compute_distinct_stats;
2030
    /* Might as well use the same minrows as above */
2031
0
    stats->minrows = 300 * stats->attstattarget;
2032
0
  }
2033
0
  else
2034
0
  {
2035
    /* Can't do much but the trivial stuff */
2036
0
    stats->compute_stats = compute_trivial_stats;
2037
    /* Might as well use the same minrows as above */
2038
0
    stats->minrows = 300 * stats->attstattarget;
2039
0
  }
2040
2041
0
  return true;
2042
0
}
2043
2044
2045
/*
2046
 *  compute_trivial_stats() -- compute very basic column statistics
2047
 *
2048
 *  We use this when we cannot find a hash "=" operator for the datatype.
2049
 *
2050
 *  We determine the fraction of non-null rows and the average datum width.
2051
 */
2052
static void
2053
compute_trivial_stats(VacAttrStatsP stats,
2054
            AnalyzeAttrFetchFunc fetchfunc,
2055
            int samplerows,
2056
            double totalrows)
2057
0
{
2058
0
  int     i;
2059
0
  int     null_cnt = 0;
2060
0
  int     nonnull_cnt = 0;
2061
0
  double    total_width = 0;
2062
0
  bool    is_varlena = (!stats->attrtype->typbyval &&
2063
0
                stats->attrtype->typlen == -1);
2064
0
  bool    is_varwidth = (!stats->attrtype->typbyval &&
2065
0
                 stats->attrtype->typlen < 0);
2066
2067
0
  for (i = 0; i < samplerows; i++)
2068
0
  {
2069
0
    Datum   value;
2070
0
    bool    isnull;
2071
2072
0
    vacuum_delay_point(true);
2073
2074
0
    value = fetchfunc(stats, i, &isnull);
2075
2076
    /* Check for null/nonnull */
2077
0
    if (isnull)
2078
0
    {
2079
0
      null_cnt++;
2080
0
      continue;
2081
0
    }
2082
0
    nonnull_cnt++;
2083
2084
    /*
2085
     * If it's a variable-width field, add up widths for average width
2086
     * calculation.  Note that if the value is toasted, we use the toasted
2087
     * width.  We don't bother with this calculation if it's a fixed-width
2088
     * type.
2089
     */
2090
0
    if (is_varlena)
2091
0
    {
2092
0
      total_width += VARSIZE_ANY(DatumGetPointer(value));
2093
0
    }
2094
0
    else if (is_varwidth)
2095
0
    {
2096
      /* must be cstring */
2097
0
      total_width += strlen(DatumGetCString(value)) + 1;
2098
0
    }
2099
0
  }
2100
2101
  /* We can only compute average width if we found some non-null values. */
2102
0
  if (nonnull_cnt > 0)
2103
0
  {
2104
0
    stats->stats_valid = true;
2105
    /* Do the simple null-frac and width stats */
2106
0
    stats->stanullfrac = (double) null_cnt / (double) samplerows;
2107
0
    if (is_varwidth)
2108
0
      stats->stawidth = total_width / (double) nonnull_cnt;
2109
0
    else
2110
0
      stats->stawidth = stats->attrtype->typlen;
2111
0
    stats->stadistinct = 0.0; /* "unknown" */
2112
0
  }
2113
0
  else if (null_cnt > 0)
2114
0
  {
2115
    /* We found only nulls; assume the column is entirely null */
2116
0
    stats->stats_valid = true;
2117
0
    stats->stanullfrac = 1.0;
2118
0
    if (is_varwidth)
2119
0
      stats->stawidth = 0; /* "unknown" */
2120
0
    else
2121
0
      stats->stawidth = stats->attrtype->typlen;
2122
0
    stats->stadistinct = 0.0; /* "unknown" */
2123
0
  }
2124
0
}
2125
2126
2127
/*
2128
 *  compute_distinct_stats() -- compute column statistics including ndistinct
2129
 *
2130
 *  We use this when we can find only an "=" operator for the datatype.
2131
 *
2132
 *  We determine the fraction of non-null rows, the average width, the
2133
 *  most common values, and the (estimated) number of distinct values.
2134
 *
2135
 *  The most common values are determined by brute force: we keep a list
2136
 *  of previously seen values, ordered by number of times seen, as we scan
2137
 *  the samples.  A newly seen value is inserted just after the last
2138
 *  multiply-seen value, causing the bottommost (oldest) singly-seen value
2139
 *  to drop off the list.  The accuracy of this method, and also its cost,
2140
 *  depend mainly on the length of the list we are willing to keep.
2141
 */
2142
static void
2143
compute_distinct_stats(VacAttrStatsP stats,
2144
             AnalyzeAttrFetchFunc fetchfunc,
2145
             int samplerows,
2146
             double totalrows)
2147
0
{
2148
0
  int     i;
2149
0
  int     null_cnt = 0;
2150
0
  int     nonnull_cnt = 0;
2151
0
  int     toowide_cnt = 0;
2152
0
  double    total_width = 0;
2153
0
  bool    is_varlena = (!stats->attrtype->typbyval &&
2154
0
                stats->attrtype->typlen == -1);
2155
0
  bool    is_varwidth = (!stats->attrtype->typbyval &&
2156
0
                 stats->attrtype->typlen < 0);
2157
0
  FmgrInfo  f_cmpeq;
2158
0
  typedef struct
2159
0
  {
2160
0
    Datum   value;
2161
0
    int     count;
2162
0
  } TrackItem;
2163
0
  TrackItem  *track;
2164
0
  int     track_cnt,
2165
0
        track_max;
2166
0
  int     num_mcv = stats->attstattarget;
2167
0
  StdAnalyzeData *mystats = (StdAnalyzeData *) stats->extra_data;
2168
2169
  /*
2170
   * We track up to 2*n values for an n-element MCV list; but at least 10
2171
   */
2172
0
  track_max = 2 * num_mcv;
2173
0
  if (track_max < 10)
2174
0
    track_max = 10;
2175
0
  track = palloc_array(TrackItem, track_max);
2176
0
  track_cnt = 0;
2177
2178
0
  fmgr_info(mystats->eqfunc, &f_cmpeq);
2179
2180
0
  for (i = 0; i < samplerows; i++)
2181
0
  {
2182
0
    Datum   value;
2183
0
    bool    isnull;
2184
0
    bool    match;
2185
0
    int     firstcount1,
2186
0
          j;
2187
2188
0
    vacuum_delay_point(true);
2189
2190
0
    value = fetchfunc(stats, i, &isnull);
2191
2192
    /* Check for null/nonnull */
2193
0
    if (isnull)
2194
0
    {
2195
0
      null_cnt++;
2196
0
      continue;
2197
0
    }
2198
0
    nonnull_cnt++;
2199
2200
    /*
2201
     * If it's a variable-width field, add up widths for average width
2202
     * calculation.  Note that if the value is toasted, we use the toasted
2203
     * width.  We don't bother with this calculation if it's a fixed-width
2204
     * type.
2205
     */
2206
0
    if (is_varlena)
2207
0
    {
2208
0
      total_width += VARSIZE_ANY(DatumGetPointer(value));
2209
2210
      /*
2211
       * If the value is toasted, we want to detoast it just once to
2212
       * avoid repeated detoastings and resultant excess memory usage
2213
       * during the comparisons.  Also, check to see if the value is
2214
       * excessively wide, and if so don't detoast at all --- just
2215
       * ignore the value.
2216
       */
2217
0
      if (toast_raw_datum_size(value) > WIDTH_THRESHOLD)
2218
0
      {
2219
0
        toowide_cnt++;
2220
0
        continue;
2221
0
      }
2222
0
      value = PointerGetDatum(PG_DETOAST_DATUM(value));
2223
0
    }
2224
0
    else if (is_varwidth)
2225
0
    {
2226
      /* must be cstring */
2227
0
      total_width += strlen(DatumGetCString(value)) + 1;
2228
0
    }
2229
2230
    /*
2231
     * See if the value matches anything we're already tracking.
2232
     */
2233
0
    match = false;
2234
0
    firstcount1 = track_cnt;
2235
0
    for (j = 0; j < track_cnt; j++)
2236
0
    {
2237
0
      if (DatumGetBool(FunctionCall2Coll(&f_cmpeq,
2238
0
                         stats->attrcollid,
2239
0
                         value, track[j].value)))
2240
0
      {
2241
0
        match = true;
2242
0
        break;
2243
0
      }
2244
0
      if (j < firstcount1 && track[j].count == 1)
2245
0
        firstcount1 = j;
2246
0
    }
2247
2248
0
    if (match)
2249
0
    {
2250
      /* Found a match */
2251
0
      track[j].count++;
2252
      /* This value may now need to "bubble up" in the track list */
2253
0
      while (j > 0 && track[j].count > track[j - 1].count)
2254
0
      {
2255
0
        swapDatum(track[j].value, track[j - 1].value);
2256
0
        swapInt(track[j].count, track[j - 1].count);
2257
0
        j--;
2258
0
      }
2259
0
    }
2260
0
    else
2261
0
    {
2262
      /* No match.  Insert at head of count-1 list */
2263
0
      if (track_cnt < track_max)
2264
0
        track_cnt++;
2265
0
      for (j = track_cnt - 1; j > firstcount1; j--)
2266
0
      {
2267
0
        track[j].value = track[j - 1].value;
2268
0
        track[j].count = track[j - 1].count;
2269
0
      }
2270
0
      if (firstcount1 < track_cnt)
2271
0
      {
2272
0
        track[firstcount1].value = value;
2273
0
        track[firstcount1].count = 1;
2274
0
      }
2275
0
    }
2276
0
  }
2277
2278
  /* We can only compute real stats if we found some non-null values. */
2279
0
  if (nonnull_cnt > 0)
2280
0
  {
2281
0
    int     nmultiple,
2282
0
          summultiple;
2283
2284
0
    stats->stats_valid = true;
2285
    /* Do the simple null-frac and width stats */
2286
0
    stats->stanullfrac = (double) null_cnt / (double) samplerows;
2287
0
    if (is_varwidth)
2288
0
      stats->stawidth = total_width / (double) nonnull_cnt;
2289
0
    else
2290
0
      stats->stawidth = stats->attrtype->typlen;
2291
2292
    /* Count the number of values we found multiple times */
2293
0
    summultiple = 0;
2294
0
    for (nmultiple = 0; nmultiple < track_cnt; nmultiple++)
2295
0
    {
2296
0
      if (track[nmultiple].count == 1)
2297
0
        break;
2298
0
      summultiple += track[nmultiple].count;
2299
0
    }
2300
2301
0
    if (nmultiple == 0)
2302
0
    {
2303
      /*
2304
       * If we found no repeated non-null values, assume it's a unique
2305
       * column; but be sure to discount for any nulls we found.
2306
       */
2307
0
      stats->stadistinct = -1.0 * (1.0 - stats->stanullfrac);
2308
0
    }
2309
0
    else if (track_cnt < track_max && toowide_cnt == 0 &&
2310
0
         nmultiple == track_cnt)
2311
0
    {
2312
      /*
2313
       * Our track list includes every value in the sample, and every
2314
       * value appeared more than once.  Assume the column has just
2315
       * these values.  (This case is meant to address columns with
2316
       * small, fixed sets of possible values, such as boolean or enum
2317
       * columns.  If there are any values that appear just once in the
2318
       * sample, including too-wide values, we should assume that that's
2319
       * not what we're dealing with.)
2320
       */
2321
0
      stats->stadistinct = track_cnt;
2322
0
    }
2323
0
    else
2324
0
    {
2325
      /*----------
2326
       * Estimate the number of distinct values using the estimator
2327
       * proposed by Haas and Stokes in IBM Research Report RJ 10025:
2328
       *    n*d / (n - f1 + f1*n/N)
2329
       * where f1 is the number of distinct values that occurred
2330
       * exactly once in our sample of n rows (from a total of N),
2331
       * and d is the total number of distinct values in the sample.
2332
       * This is their Duj1 estimator; the other estimators they
2333
       * recommend are considerably more complex, and are numerically
2334
       * very unstable when n is much smaller than N.
2335
       *
2336
       * In this calculation, we consider only non-nulls.  We used to
2337
       * include rows with null values in the n and N counts, but that
2338
       * leads to inaccurate answers in columns with many nulls, and
2339
       * it's intuitively bogus anyway considering the desired result is
2340
       * the number of distinct non-null values.
2341
       *
2342
       * We assume (not very reliably!) that all the multiply-occurring
2343
       * values are reflected in the final track[] list, and the other
2344
       * nonnull values all appeared but once.  (XXX this usually
2345
       * results in a drastic overestimate of ndistinct.  Can we do
2346
       * any better?)
2347
       *----------
2348
       */
2349
0
      int     f1 = nonnull_cnt - summultiple;
2350
0
      int     d = f1 + nmultiple;
2351
0
      double    n = samplerows - null_cnt;
2352
0
      double    N = totalrows * (1.0 - stats->stanullfrac);
2353
0
      double    stadistinct;
2354
2355
      /* N == 0 shouldn't happen, but just in case ... */
2356
0
      if (N > 0)
2357
0
        stadistinct = (n * d) / ((n - f1) + f1 * n / N);
2358
0
      else
2359
0
        stadistinct = 0;
2360
2361
      /* Clamp to sane range in case of roundoff error */
2362
0
      if (stadistinct < d)
2363
0
        stadistinct = d;
2364
0
      if (stadistinct > N)
2365
0
        stadistinct = N;
2366
      /* And round to integer */
2367
0
      stats->stadistinct = floor(stadistinct + 0.5);
2368
0
    }
2369
2370
    /*
2371
     * If we estimated the number of distinct values at more than 10% of
2372
     * the total row count (a very arbitrary limit), then assume that
2373
     * stadistinct should scale with the row count rather than be a fixed
2374
     * value.
2375
     */
2376
0
    if (stats->stadistinct > 0.1 * totalrows)
2377
0
      stats->stadistinct = -(stats->stadistinct / totalrows);
2378
2379
    /*
2380
     * Decide how many values are worth storing as most-common values. If
2381
     * we are able to generate a complete MCV list (all the values in the
2382
     * sample will fit, and we think these are all the ones in the table),
2383
     * then do so.  Otherwise, store only those values that are
2384
     * significantly more common than the values not in the list.
2385
     *
2386
     * Note: the first of these cases is meant to address columns with
2387
     * small, fixed sets of possible values, such as boolean or enum
2388
     * columns.  If we can *completely* represent the column population by
2389
     * an MCV list that will fit into the stats target, then we should do
2390
     * so and thus provide the planner with complete information.  But if
2391
     * the MCV list is not complete, it's generally worth being more
2392
     * selective, and not just filling it all the way up to the stats
2393
     * target.
2394
     */
2395
0
    if (track_cnt < track_max && toowide_cnt == 0 &&
2396
0
      stats->stadistinct > 0 &&
2397
0
      track_cnt <= num_mcv)
2398
0
    {
2399
      /* Track list includes all values seen, and all will fit */
2400
0
      num_mcv = track_cnt;
2401
0
    }
2402
0
    else
2403
0
    {
2404
0
      int      *mcv_counts;
2405
2406
      /* Incomplete list; decide how many values are worth keeping */
2407
0
      if (num_mcv > track_cnt)
2408
0
        num_mcv = track_cnt;
2409
2410
0
      if (num_mcv > 0)
2411
0
      {
2412
0
        mcv_counts = palloc_array(int, num_mcv);
2413
0
        for (i = 0; i < num_mcv; i++)
2414
0
          mcv_counts[i] = track[i].count;
2415
2416
0
        num_mcv = analyze_mcv_list(mcv_counts, num_mcv,
2417
0
                       stats->stadistinct,
2418
0
                       stats->stanullfrac,
2419
0
                       samplerows, totalrows);
2420
0
      }
2421
0
    }
2422
2423
    /* Generate MCV slot entry */
2424
0
    if (num_mcv > 0)
2425
0
    {
2426
0
      MemoryContext old_context;
2427
0
      Datum    *mcv_values;
2428
0
      float4     *mcv_freqs;
2429
2430
      /* Must copy the target values into anl_context */
2431
0
      old_context = MemoryContextSwitchTo(stats->anl_context);
2432
0
      mcv_values = palloc_array(Datum, num_mcv);
2433
0
      mcv_freqs = palloc_array(float4, num_mcv);
2434
0
      for (i = 0; i < num_mcv; i++)
2435
0
      {
2436
0
        mcv_values[i] = datumCopy(track[i].value,
2437
0
                      stats->attrtype->typbyval,
2438
0
                      stats->attrtype->typlen);
2439
0
        mcv_freqs[i] = (double) track[i].count / (double) samplerows;
2440
0
      }
2441
0
      MemoryContextSwitchTo(old_context);
2442
2443
0
      stats->stakind[0] = STATISTIC_KIND_MCV;
2444
0
      stats->staop[0] = mystats->eqopr;
2445
0
      stats->stacoll[0] = stats->attrcollid;
2446
0
      stats->stanumbers[0] = mcv_freqs;
2447
0
      stats->numnumbers[0] = num_mcv;
2448
0
      stats->stavalues[0] = mcv_values;
2449
0
      stats->numvalues[0] = num_mcv;
2450
2451
      /*
2452
       * Accept the defaults for stats->statypid and others. They have
2453
       * been set before we were called (see vacuum.h)
2454
       */
2455
0
    }
2456
0
  }
2457
0
  else if (null_cnt > 0)
2458
0
  {
2459
    /* We found only nulls; assume the column is entirely null */
2460
0
    stats->stats_valid = true;
2461
0
    stats->stanullfrac = 1.0;
2462
0
    if (is_varwidth)
2463
0
      stats->stawidth = 0; /* "unknown" */
2464
0
    else
2465
0
      stats->stawidth = stats->attrtype->typlen;
2466
0
    stats->stadistinct = 0.0; /* "unknown" */
2467
0
  }
2468
2469
  /* We don't need to bother cleaning up any of our temporary palloc's */
2470
0
}
2471
2472
2473
/*
2474
 *  compute_scalar_stats() -- compute column statistics
2475
 *
2476
 *  We use this when we can find "=" and "<" operators for the datatype.
2477
 *
2478
 *  We determine the fraction of non-null rows, the average width, the
2479
 *  most common values, the (estimated) number of distinct values, the
2480
 *  distribution histogram, and the correlation of physical to logical order.
2481
 *
2482
 *  The desired stats can be determined fairly easily after sorting the
2483
 *  data values into order.
2484
 */
2485
static void
2486
compute_scalar_stats(VacAttrStatsP stats,
2487
           AnalyzeAttrFetchFunc fetchfunc,
2488
           int samplerows,
2489
           double totalrows)
2490
0
{
2491
0
  int     i;
2492
0
  int     null_cnt = 0;
2493
0
  int     nonnull_cnt = 0;
2494
0
  int     toowide_cnt = 0;
2495
0
  double    total_width = 0;
2496
0
  bool    is_varlena = (!stats->attrtype->typbyval &&
2497
0
                stats->attrtype->typlen == -1);
2498
0
  bool    is_varwidth = (!stats->attrtype->typbyval &&
2499
0
                 stats->attrtype->typlen < 0);
2500
0
  double    corr_xysum;
2501
0
  SortSupportData ssup;
2502
0
  ScalarItem *values;
2503
0
  int     values_cnt = 0;
2504
0
  int      *tupnoLink;
2505
0
  ScalarMCVItem *track;
2506
0
  int     track_cnt = 0;
2507
0
  int     num_mcv = stats->attstattarget;
2508
0
  int     num_bins = stats->attstattarget;
2509
0
  StdAnalyzeData *mystats = (StdAnalyzeData *) stats->extra_data;
2510
2511
0
  values = palloc_array(ScalarItem, samplerows);
2512
0
  tupnoLink = palloc_array(int, samplerows);
2513
0
  track = palloc_array(ScalarMCVItem, num_mcv);
2514
2515
0
  memset(&ssup, 0, sizeof(ssup));
2516
0
  ssup.ssup_cxt = CurrentMemoryContext;
2517
0
  ssup.ssup_collation = stats->attrcollid;
2518
0
  ssup.ssup_nulls_first = false;
2519
2520
  /*
2521
   * For now, don't perform abbreviated key conversion, because full values
2522
   * are required for MCV slot generation.  Supporting that optimization
2523
   * would necessitate teaching compare_scalars() to call a tie-breaker.
2524
   */
2525
0
  ssup.abbreviate = false;
2526
2527
0
  PrepareSortSupportFromOrderingOp(mystats->ltopr, &ssup);
2528
2529
  /* Initial scan to find sortable values */
2530
0
  for (i = 0; i < samplerows; i++)
2531
0
  {
2532
0
    Datum   value;
2533
0
    bool    isnull;
2534
2535
0
    vacuum_delay_point(true);
2536
2537
0
    value = fetchfunc(stats, i, &isnull);
2538
2539
    /* Check for null/nonnull */
2540
0
    if (isnull)
2541
0
    {
2542
0
      null_cnt++;
2543
0
      continue;
2544
0
    }
2545
0
    nonnull_cnt++;
2546
2547
    /*
2548
     * If it's a variable-width field, add up widths for average width
2549
     * calculation.  Note that if the value is toasted, we use the toasted
2550
     * width.  We don't bother with this calculation if it's a fixed-width
2551
     * type.
2552
     */
2553
0
    if (is_varlena)
2554
0
    {
2555
0
      total_width += VARSIZE_ANY(DatumGetPointer(value));
2556
2557
      /*
2558
       * If the value is toasted, we want to detoast it just once to
2559
       * avoid repeated detoastings and resultant excess memory usage
2560
       * during the comparisons.  Also, check to see if the value is
2561
       * excessively wide, and if so don't detoast at all --- just
2562
       * ignore the value.
2563
       */
2564
0
      if (toast_raw_datum_size(value) > WIDTH_THRESHOLD)
2565
0
      {
2566
0
        toowide_cnt++;
2567
0
        continue;
2568
0
      }
2569
0
      value = PointerGetDatum(PG_DETOAST_DATUM(value));
2570
0
    }
2571
0
    else if (is_varwidth)
2572
0
    {
2573
      /* must be cstring */
2574
0
      total_width += strlen(DatumGetCString(value)) + 1;
2575
0
    }
2576
2577
    /* Add it to the list to be sorted */
2578
0
    values[values_cnt].value = value;
2579
0
    values[values_cnt].tupno = values_cnt;
2580
0
    tupnoLink[values_cnt] = values_cnt;
2581
0
    values_cnt++;
2582
0
  }
2583
2584
  /* We can only compute real stats if we found some sortable values. */
2585
0
  if (values_cnt > 0)
2586
0
  {
2587
0
    int     ndistinct,  /* # distinct values in sample */
2588
0
          nmultiple,  /* # that appear multiple times */
2589
0
          num_hist,
2590
0
          dups_cnt;
2591
0
    int     slot_idx = 0;
2592
0
    CompareScalarsContext cxt;
2593
2594
    /* Sort the collected values */
2595
0
    cxt.ssup = &ssup;
2596
0
    cxt.tupnoLink = tupnoLink;
2597
0
    qsort_interruptible(values, values_cnt, sizeof(ScalarItem),
2598
0
              compare_scalars, &cxt);
2599
2600
    /*
2601
     * Now scan the values in order, find the most common ones, and also
2602
     * accumulate ordering-correlation statistics.
2603
     *
2604
     * To determine which are most common, we first have to count the
2605
     * number of duplicates of each value.  The duplicates are adjacent in
2606
     * the sorted list, so a brute-force approach is to compare successive
2607
     * datum values until we find two that are not equal. However, that
2608
     * requires N-1 invocations of the datum comparison routine, which are
2609
     * completely redundant with work that was done during the sort.  (The
2610
     * sort algorithm must at some point have compared each pair of items
2611
     * that are adjacent in the sorted order; otherwise it could not know
2612
     * that it's ordered the pair correctly.) We exploit this by having
2613
     * compare_scalars remember the highest tupno index that each
2614
     * ScalarItem has been found equal to.  At the end of the sort, a
2615
     * ScalarItem's tupnoLink will still point to itself if and only if it
2616
     * is the last item of its group of duplicates (since the group will
2617
     * be ordered by tupno).
2618
     */
2619
0
    corr_xysum = 0;
2620
0
    ndistinct = 0;
2621
0
    nmultiple = 0;
2622
0
    dups_cnt = 0;
2623
0
    for (i = 0; i < values_cnt; i++)
2624
0
    {
2625
0
      int     tupno = values[i].tupno;
2626
2627
0
      corr_xysum += ((double) i) * ((double) tupno);
2628
0
      dups_cnt++;
2629
0
      if (tupnoLink[tupno] == tupno)
2630
0
      {
2631
        /* Reached end of duplicates of this value */
2632
0
        ndistinct++;
2633
0
        if (dups_cnt > 1)
2634
0
        {
2635
0
          nmultiple++;
2636
0
          if (track_cnt < num_mcv ||
2637
0
            dups_cnt > track[track_cnt - 1].count)
2638
0
          {
2639
            /*
2640
             * Found a new item for the mcv list; find its
2641
             * position, bubbling down old items if needed. Loop
2642
             * invariant is that j points at an empty/ replaceable
2643
             * slot.
2644
             */
2645
0
            int     j;
2646
2647
0
            if (track_cnt < num_mcv)
2648
0
              track_cnt++;
2649
0
            for (j = track_cnt - 1; j > 0; j--)
2650
0
            {
2651
0
              if (dups_cnt <= track[j - 1].count)
2652
0
                break;
2653
0
              track[j].count = track[j - 1].count;
2654
0
              track[j].first = track[j - 1].first;
2655
0
            }
2656
0
            track[j].count = dups_cnt;
2657
0
            track[j].first = i + 1 - dups_cnt;
2658
0
          }
2659
0
        }
2660
0
        dups_cnt = 0;
2661
0
      }
2662
0
    }
2663
2664
0
    stats->stats_valid = true;
2665
    /* Do the simple null-frac and width stats */
2666
0
    stats->stanullfrac = (double) null_cnt / (double) samplerows;
2667
0
    if (is_varwidth)
2668
0
      stats->stawidth = total_width / (double) nonnull_cnt;
2669
0
    else
2670
0
      stats->stawidth = stats->attrtype->typlen;
2671
2672
0
    if (nmultiple == 0)
2673
0
    {
2674
      /*
2675
       * If we found no repeated non-null values, assume it's a unique
2676
       * column; but be sure to discount for any nulls we found.
2677
       */
2678
0
      stats->stadistinct = -1.0 * (1.0 - stats->stanullfrac);
2679
0
    }
2680
0
    else if (toowide_cnt == 0 && nmultiple == ndistinct)
2681
0
    {
2682
      /*
2683
       * Every value in the sample appeared more than once.  Assume the
2684
       * column has just these values.  (This case is meant to address
2685
       * columns with small, fixed sets of possible values, such as
2686
       * boolean or enum columns.  If there are any values that appear
2687
       * just once in the sample, including too-wide values, we should
2688
       * assume that that's not what we're dealing with.)
2689
       */
2690
0
      stats->stadistinct = ndistinct;
2691
0
    }
2692
0
    else
2693
0
    {
2694
      /*----------
2695
       * Estimate the number of distinct values using the estimator
2696
       * proposed by Haas and Stokes in IBM Research Report RJ 10025:
2697
       *    n*d / (n - f1 + f1*n/N)
2698
       * where f1 is the number of distinct values that occurred
2699
       * exactly once in our sample of n rows (from a total of N),
2700
       * and d is the total number of distinct values in the sample.
2701
       * This is their Duj1 estimator; the other estimators they
2702
       * recommend are considerably more complex, and are numerically
2703
       * very unstable when n is much smaller than N.
2704
       *
2705
       * In this calculation, we consider only non-nulls.  We used to
2706
       * include rows with null values in the n and N counts, but that
2707
       * leads to inaccurate answers in columns with many nulls, and
2708
       * it's intuitively bogus anyway considering the desired result is
2709
       * the number of distinct non-null values.
2710
       *
2711
       * Overwidth values are assumed to have been distinct.
2712
       *----------
2713
       */
2714
0
      int     f1 = ndistinct - nmultiple + toowide_cnt;
2715
0
      int     d = f1 + nmultiple;
2716
0
      double    n = samplerows - null_cnt;
2717
0
      double    N = totalrows * (1.0 - stats->stanullfrac);
2718
0
      double    stadistinct;
2719
2720
      /* N == 0 shouldn't happen, but just in case ... */
2721
0
      if (N > 0)
2722
0
        stadistinct = (n * d) / ((n - f1) + f1 * n / N);
2723
0
      else
2724
0
        stadistinct = 0;
2725
2726
      /* Clamp to sane range in case of roundoff error */
2727
0
      if (stadistinct < d)
2728
0
        stadistinct = d;
2729
0
      if (stadistinct > N)
2730
0
        stadistinct = N;
2731
      /* And round to integer */
2732
0
      stats->stadistinct = floor(stadistinct + 0.5);
2733
0
    }
2734
2735
    /*
2736
     * If we estimated the number of distinct values at more than 10% of
2737
     * the total row count (a very arbitrary limit), then assume that
2738
     * stadistinct should scale with the row count rather than be a fixed
2739
     * value.
2740
     */
2741
0
    if (stats->stadistinct > 0.1 * totalrows)
2742
0
      stats->stadistinct = -(stats->stadistinct / totalrows);
2743
2744
    /*
2745
     * Decide how many values are worth storing as most-common values. If
2746
     * we are able to generate a complete MCV list (all the values in the
2747
     * sample will fit, and we think these are all the ones in the table),
2748
     * then do so.  Otherwise, store only those values that are
2749
     * significantly more common than the values not in the list.
2750
     *
2751
     * Note: the first of these cases is meant to address columns with
2752
     * small, fixed sets of possible values, such as boolean or enum
2753
     * columns.  If we can *completely* represent the column population by
2754
     * an MCV list that will fit into the stats target, then we should do
2755
     * so and thus provide the planner with complete information.  But if
2756
     * the MCV list is not complete, it's generally worth being more
2757
     * selective, and not just filling it all the way up to the stats
2758
     * target.
2759
     */
2760
0
    if (track_cnt == ndistinct && toowide_cnt == 0 &&
2761
0
      stats->stadistinct > 0 &&
2762
0
      track_cnt <= num_mcv)
2763
0
    {
2764
      /* Track list includes all values seen, and all will fit */
2765
0
      num_mcv = track_cnt;
2766
0
    }
2767
0
    else
2768
0
    {
2769
0
      int      *mcv_counts;
2770
2771
      /* Incomplete list; decide how many values are worth keeping */
2772
0
      if (num_mcv > track_cnt)
2773
0
        num_mcv = track_cnt;
2774
2775
0
      if (num_mcv > 0)
2776
0
      {
2777
0
        mcv_counts = palloc_array(int, num_mcv);
2778
0
        for (i = 0; i < num_mcv; i++)
2779
0
          mcv_counts[i] = track[i].count;
2780
2781
0
        num_mcv = analyze_mcv_list(mcv_counts, num_mcv,
2782
0
                       stats->stadistinct,
2783
0
                       stats->stanullfrac,
2784
0
                       samplerows, totalrows);
2785
0
      }
2786
0
    }
2787
2788
    /* Generate MCV slot entry */
2789
0
    if (num_mcv > 0)
2790
0
    {
2791
0
      MemoryContext old_context;
2792
0
      Datum    *mcv_values;
2793
0
      float4     *mcv_freqs;
2794
2795
      /* Must copy the target values into anl_context */
2796
0
      old_context = MemoryContextSwitchTo(stats->anl_context);
2797
0
      mcv_values = palloc_array(Datum, num_mcv);
2798
0
      mcv_freqs = palloc_array(float4, num_mcv);
2799
0
      for (i = 0; i < num_mcv; i++)
2800
0
      {
2801
0
        mcv_values[i] = datumCopy(values[track[i].first].value,
2802
0
                      stats->attrtype->typbyval,
2803
0
                      stats->attrtype->typlen);
2804
0
        mcv_freqs[i] = (double) track[i].count / (double) samplerows;
2805
0
      }
2806
0
      MemoryContextSwitchTo(old_context);
2807
2808
0
      stats->stakind[slot_idx] = STATISTIC_KIND_MCV;
2809
0
      stats->staop[slot_idx] = mystats->eqopr;
2810
0
      stats->stacoll[slot_idx] = stats->attrcollid;
2811
0
      stats->stanumbers[slot_idx] = mcv_freqs;
2812
0
      stats->numnumbers[slot_idx] = num_mcv;
2813
0
      stats->stavalues[slot_idx] = mcv_values;
2814
0
      stats->numvalues[slot_idx] = num_mcv;
2815
2816
      /*
2817
       * Accept the defaults for stats->statypid and others. They have
2818
       * been set before we were called (see vacuum.h)
2819
       */
2820
0
      slot_idx++;
2821
0
    }
2822
2823
    /*
2824
     * Generate a histogram slot entry if there are at least two distinct
2825
     * values not accounted for in the MCV list.  (This ensures the
2826
     * histogram won't collapse to empty or a singleton.)
2827
     */
2828
0
    num_hist = ndistinct - num_mcv;
2829
0
    if (num_hist > num_bins)
2830
0
      num_hist = num_bins + 1;
2831
0
    if (num_hist >= 2)
2832
0
    {
2833
0
      MemoryContext old_context;
2834
0
      Datum    *hist_values;
2835
0
      int     nvals;
2836
0
      int     pos,
2837
0
            posfrac,
2838
0
            delta,
2839
0
            deltafrac;
2840
2841
      /* Sort the MCV items into position order to speed next loop */
2842
0
      qsort_interruptible(track, num_mcv, sizeof(ScalarMCVItem),
2843
0
                compare_mcvs, NULL);
2844
2845
      /*
2846
       * Collapse out the MCV items from the values[] array.
2847
       *
2848
       * Note we destroy the values[] array here... but we don't need it
2849
       * for anything more.  We do, however, still need values_cnt.
2850
       * nvals will be the number of remaining entries in values[].
2851
       */
2852
0
      if (num_mcv > 0)
2853
0
      {
2854
0
        int     src,
2855
0
              dest;
2856
0
        int     j;
2857
2858
0
        src = dest = 0;
2859
0
        j = 0;      /* index of next interesting MCV item */
2860
0
        while (src < values_cnt)
2861
0
        {
2862
0
          int     ncopy;
2863
2864
0
          if (j < num_mcv)
2865
0
          {
2866
0
            int     first = track[j].first;
2867
2868
0
            if (src >= first)
2869
0
            {
2870
              /* advance past this MCV item */
2871
0
              src = first + track[j].count;
2872
0
              j++;
2873
0
              continue;
2874
0
            }
2875
0
            ncopy = first - src;
2876
0
          }
2877
0
          else
2878
0
            ncopy = values_cnt - src;
2879
0
          memmove(&values[dest], &values[src],
2880
0
              ncopy * sizeof(ScalarItem));
2881
0
          src += ncopy;
2882
0
          dest += ncopy;
2883
0
        }
2884
0
        nvals = dest;
2885
0
      }
2886
0
      else
2887
0
        nvals = values_cnt;
2888
0
      Assert(nvals >= num_hist);
2889
2890
      /* Must copy the target values into anl_context */
2891
0
      old_context = MemoryContextSwitchTo(stats->anl_context);
2892
0
      hist_values = palloc_array(Datum, num_hist);
2893
2894
      /*
2895
       * The object of this loop is to copy the first and last values[]
2896
       * entries along with evenly-spaced values in between.  So the
2897
       * i'th value is values[(i * (nvals - 1)) / (num_hist - 1)].  But
2898
       * computing that subscript directly risks integer overflow when
2899
       * the stats target is more than a couple thousand.  Instead we
2900
       * add (nvals - 1) / (num_hist - 1) to pos at each step, tracking
2901
       * the integral and fractional parts of the sum separately.
2902
       */
2903
0
      delta = (nvals - 1) / (num_hist - 1);
2904
0
      deltafrac = (nvals - 1) % (num_hist - 1);
2905
0
      pos = posfrac = 0;
2906
2907
0
      for (i = 0; i < num_hist; i++)
2908
0
      {
2909
0
        hist_values[i] = datumCopy(values[pos].value,
2910
0
                       stats->attrtype->typbyval,
2911
0
                       stats->attrtype->typlen);
2912
0
        pos += delta;
2913
0
        posfrac += deltafrac;
2914
0
        if (posfrac >= (num_hist - 1))
2915
0
        {
2916
          /* fractional part exceeds 1, carry to integer part */
2917
0
          pos++;
2918
0
          posfrac -= (num_hist - 1);
2919
0
        }
2920
0
      }
2921
2922
0
      MemoryContextSwitchTo(old_context);
2923
2924
0
      stats->stakind[slot_idx] = STATISTIC_KIND_HISTOGRAM;
2925
0
      stats->staop[slot_idx] = mystats->ltopr;
2926
0
      stats->stacoll[slot_idx] = stats->attrcollid;
2927
0
      stats->stavalues[slot_idx] = hist_values;
2928
0
      stats->numvalues[slot_idx] = num_hist;
2929
2930
      /*
2931
       * Accept the defaults for stats->statypid and others. They have
2932
       * been set before we were called (see vacuum.h)
2933
       */
2934
0
      slot_idx++;
2935
0
    }
2936
2937
    /* Generate a correlation entry if there are multiple values */
2938
0
    if (values_cnt > 1)
2939
0
    {
2940
0
      MemoryContext old_context;
2941
0
      float4     *corrs;
2942
0
      double    corr_xsum,
2943
0
            corr_x2sum;
2944
2945
      /* Must copy the target values into anl_context */
2946
0
      old_context = MemoryContextSwitchTo(stats->anl_context);
2947
0
      corrs = palloc_object(float4);
2948
0
      MemoryContextSwitchTo(old_context);
2949
2950
      /*----------
2951
       * Since we know the x and y value sets are both
2952
       *    0, 1, ..., values_cnt-1
2953
       * we have sum(x) = sum(y) =
2954
       *    (values_cnt-1)*values_cnt / 2
2955
       * and sum(x^2) = sum(y^2) =
2956
       *    (values_cnt-1)*values_cnt*(2*values_cnt-1) / 6.
2957
       *----------
2958
       */
2959
0
      corr_xsum = ((double) (values_cnt - 1)) *
2960
0
        ((double) values_cnt) / 2.0;
2961
0
      corr_x2sum = ((double) (values_cnt - 1)) *
2962
0
        ((double) values_cnt) * (double) (2 * values_cnt - 1) / 6.0;
2963
2964
      /* And the correlation coefficient reduces to */
2965
0
      corrs[0] = (values_cnt * corr_xysum - corr_xsum * corr_xsum) /
2966
0
        (values_cnt * corr_x2sum - corr_xsum * corr_xsum);
2967
2968
0
      stats->stakind[slot_idx] = STATISTIC_KIND_CORRELATION;
2969
0
      stats->staop[slot_idx] = mystats->ltopr;
2970
0
      stats->stacoll[slot_idx] = stats->attrcollid;
2971
0
      stats->stanumbers[slot_idx] = corrs;
2972
0
      stats->numnumbers[slot_idx] = 1;
2973
0
      slot_idx++;
2974
0
    }
2975
0
  }
2976
0
  else if (nonnull_cnt > 0)
2977
0
  {
2978
    /* We found some non-null values, but they were all too wide */
2979
0
    Assert(nonnull_cnt == toowide_cnt);
2980
0
    stats->stats_valid = true;
2981
    /* Do the simple null-frac and width stats */
2982
0
    stats->stanullfrac = (double) null_cnt / (double) samplerows;
2983
0
    if (is_varwidth)
2984
0
      stats->stawidth = total_width / (double) nonnull_cnt;
2985
0
    else
2986
0
      stats->stawidth = stats->attrtype->typlen;
2987
    /* Assume all too-wide values are distinct, so it's a unique column */
2988
0
    stats->stadistinct = -1.0 * (1.0 - stats->stanullfrac);
2989
0
  }
2990
0
  else if (null_cnt > 0)
2991
0
  {
2992
    /* We found only nulls; assume the column is entirely null */
2993
0
    stats->stats_valid = true;
2994
0
    stats->stanullfrac = 1.0;
2995
0
    if (is_varwidth)
2996
0
      stats->stawidth = 0; /* "unknown" */
2997
0
    else
2998
0
      stats->stawidth = stats->attrtype->typlen;
2999
0
    stats->stadistinct = 0.0; /* "unknown" */
3000
0
  }
3001
3002
  /* We don't need to bother cleaning up any of our temporary palloc's */
3003
0
}
3004
3005
/*
3006
 * Comparator for sorting ScalarItems
3007
 *
3008
 * Aside from sorting the items, we update the tupnoLink[] array
3009
 * whenever two ScalarItems are found to contain equal datums.  The array
3010
 * is indexed by tupno; for each ScalarItem, it contains the highest
3011
 * tupno that that item's datum has been found to be equal to.  This allows
3012
 * us to avoid additional comparisons in compute_scalar_stats().
3013
 */
3014
static int
3015
compare_scalars(const void *a, const void *b, void *arg)
3016
0
{
3017
0
  Datum   da = ((const ScalarItem *) a)->value;
3018
0
  int     ta = ((const ScalarItem *) a)->tupno;
3019
0
  Datum   db = ((const ScalarItem *) b)->value;
3020
0
  int     tb = ((const ScalarItem *) b)->tupno;
3021
0
  CompareScalarsContext *cxt = (CompareScalarsContext *) arg;
3022
0
  int     compare;
3023
3024
0
  compare = ApplySortComparator(da, false, db, false, cxt->ssup);
3025
0
  if (compare != 0)
3026
0
    return compare;
3027
3028
  /*
3029
   * The two datums are equal, so update cxt->tupnoLink[].
3030
   */
3031
0
  if (cxt->tupnoLink[ta] < tb)
3032
0
    cxt->tupnoLink[ta] = tb;
3033
0
  if (cxt->tupnoLink[tb] < ta)
3034
0
    cxt->tupnoLink[tb] = ta;
3035
3036
  /*
3037
   * For equal datums, sort by tupno
3038
   */
3039
0
  return ta - tb;
3040
0
}
3041
3042
/*
3043
 * Comparator for sorting ScalarMCVItems by position
3044
 */
3045
static int
3046
compare_mcvs(const void *a, const void *b, void *arg)
3047
0
{
3048
0
  int     da = ((const ScalarMCVItem *) a)->first;
3049
0
  int     db = ((const ScalarMCVItem *) b)->first;
3050
3051
0
  return da - db;
3052
0
}
3053
3054
/*
3055
 * Analyze the list of common values in the sample and decide how many are
3056
 * worth storing in the table's MCV list.
3057
 *
3058
 * mcv_counts is assumed to be a list of the counts of the most common values
3059
 * seen in the sample, starting with the most common.  The return value is the
3060
 * number that are significantly more common than the values not in the list,
3061
 * and which are therefore deemed worth storing in the table's MCV list.
3062
 */
3063
static int
3064
analyze_mcv_list(int *mcv_counts,
3065
         int num_mcv,
3066
         double stadistinct,
3067
         double stanullfrac,
3068
         int samplerows,
3069
         double totalrows)
3070
0
{
3071
0
  double    ndistinct_table;
3072
0
  double    sumcount;
3073
0
  int     i;
3074
3075
  /*
3076
   * If the entire table was sampled, keep the whole list.  This also
3077
   * protects us against division by zero in the code below.
3078
   */
3079
0
  if (samplerows == totalrows || totalrows <= 1.0)
3080
0
    return num_mcv;
3081
3082
  /* Re-extract the estimated number of distinct nonnull values in table */
3083
0
  ndistinct_table = stadistinct;
3084
0
  if (ndistinct_table < 0)
3085
0
    ndistinct_table = -ndistinct_table * totalrows;
3086
3087
  /*
3088
   * Exclude the least common values from the MCV list, if they are not
3089
   * significantly more common than the estimated selectivity they would
3090
   * have if they weren't in the list.  All non-MCV values are assumed to be
3091
   * equally common, after taking into account the frequencies of all the
3092
   * values in the MCV list and the number of nulls (c.f. eqsel()).
3093
   *
3094
   * Here sumcount tracks the total count of all but the last (least common)
3095
   * value in the MCV list, allowing us to determine the effect of excluding
3096
   * that value from the list.
3097
   *
3098
   * Note that we deliberately do this by removing values from the full
3099
   * list, rather than starting with an empty list and adding values,
3100
   * because the latter approach can fail to add any values if all the most
3101
   * common values have around the same frequency and make up the majority
3102
   * of the table, so that the overall average frequency of all values is
3103
   * roughly the same as that of the common values.  This would lead to any
3104
   * uncommon values being significantly overestimated.
3105
   */
3106
0
  sumcount = 0.0;
3107
0
  for (i = 0; i < num_mcv - 1; i++)
3108
0
    sumcount += mcv_counts[i];
3109
3110
0
  while (num_mcv > 0)
3111
0
  {
3112
0
    double    selec,
3113
0
          otherdistinct,
3114
0
          N,
3115
0
          n,
3116
0
          K,
3117
0
          variance,
3118
0
          stddev;
3119
3120
    /*
3121
     * Estimated selectivity the least common value would have if it
3122
     * wasn't in the MCV list (c.f. eqsel()).
3123
     */
3124
0
    selec = 1.0 - sumcount / samplerows - stanullfrac;
3125
0
    if (selec < 0.0)
3126
0
      selec = 0.0;
3127
0
    if (selec > 1.0)
3128
0
      selec = 1.0;
3129
0
    otherdistinct = ndistinct_table - (num_mcv - 1);
3130
0
    if (otherdistinct > 1)
3131
0
      selec /= otherdistinct;
3132
3133
    /*
3134
     * If the value is kept in the MCV list, its population frequency is
3135
     * assumed to equal its sample frequency.  We use the lower end of a
3136
     * textbook continuity-corrected Wald-type confidence interval to
3137
     * determine if that is significantly more common than the non-MCV
3138
     * frequency --- specifically we assume the population frequency is
3139
     * highly likely to be within around 2 standard errors of the sample
3140
     * frequency, which equates to an interval of 2 standard deviations
3141
     * either side of the sample count, plus an additional 0.5 for the
3142
     * continuity correction.  Since we are sampling without replacement,
3143
     * this is a hypergeometric distribution.
3144
     *
3145
     * XXX: Empirically, this approach seems to work quite well, but it
3146
     * may be worth considering more advanced techniques for estimating
3147
     * the confidence interval of the hypergeometric distribution.
3148
     */
3149
0
    N = totalrows;
3150
0
    n = samplerows;
3151
0
    K = N * mcv_counts[num_mcv - 1] / n;
3152
0
    variance = n * K * (N - K) * (N - n) / (N * N * (N - 1));
3153
0
    stddev = sqrt(variance);
3154
3155
0
    if (mcv_counts[num_mcv - 1] > selec * samplerows + 2 * stddev + 0.5)
3156
0
    {
3157
      /*
3158
       * The value is significantly more common than the non-MCV
3159
       * selectivity would suggest.  Keep it, and all the other more
3160
       * common values in the list.
3161
       */
3162
0
      break;
3163
0
    }
3164
0
    else
3165
0
    {
3166
      /* Discard this value and consider the next least common value */
3167
0
      num_mcv--;
3168
0
      if (num_mcv == 0)
3169
0
        break;
3170
0
      sumcount -= mcv_counts[num_mcv - 1];
3171
0
    }
3172
0
  }
3173
0
  return num_mcv;
3174
0
}