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