PostgreSQL Source Code  git master
statistics.h File Reference
#include "commands/vacuum.h"
#include "nodes/pathnodes.h"
Include dependency graph for statistics.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  MVNDistinctItem
 
struct  MVNDistinct
 
struct  MVDependency
 
struct  MVDependencies
 
struct  MCVItem
 
struct  MCVList
 

Macros

#define STATS_MAX_DIMENSIONS   8 /* max number of attributes */
 
#define STATS_NDISTINCT_MAGIC   0xA352BFA4 /* struct identifier */
 
#define STATS_NDISTINCT_TYPE_BASIC   1 /* struct version */
 
#define STATS_DEPS_MAGIC   0xB4549A2C /* marks serialized bytea */
 
#define STATS_DEPS_TYPE_BASIC   1 /* basic dependencies type */
 
#define STATS_MCV_MAGIC   0xE1A651C2 /* marks serialized bytea */
 
#define STATS_MCV_TYPE_BASIC   1 /* basic MCV list type */
 
#define STATS_MCVLIST_MAX_ITEMS   10000
 

Typedefs

typedef struct MVNDistinctItem MVNDistinctItem
 
typedef struct MVNDistinct MVNDistinct
 
typedef struct MVDependency MVDependency
 
typedef struct MVDependencies MVDependencies
 
typedef struct MCVItem MCVItem
 
typedef struct MCVList MCVList
 

Functions

MVNDistinctstatext_ndistinct_load (Oid mvoid)
 
MVDependenciesstatext_dependencies_load (Oid mvoid)
 
MCVListstatext_mcv_load (Oid mvoid)
 
void BuildRelationExtStatistics (Relation onerel, double totalrows, int numrows, HeapTuple *rows, int natts, VacAttrStats **vacattrstats)
 
int ComputeExtStatisticsRows (Relation onerel, int natts, VacAttrStats **stats)
 
bool statext_is_kind_built (HeapTuple htup, char kind)
 
Selectivity dependencies_clauselist_selectivity (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
 
Selectivity statext_clauselist_selectivity (PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
 
bool has_stats_of_kind (List *stats, char requiredkind)
 
StatisticExtInfochoose_best_statistics (List *stats, char requiredkind, Bitmapset **clause_attnums, int nclauses)
 

Macro Definition Documentation

◆ STATS_DEPS_MAGIC

#define STATS_DEPS_MAGIC   0xB4549A2C /* marks serialized bytea */

Definition at line 42 of file statistics.h.

Referenced by statext_dependencies_build(), and statext_dependencies_deserialize().

◆ STATS_DEPS_TYPE_BASIC

#define STATS_DEPS_TYPE_BASIC   1 /* basic dependencies type */

Definition at line 43 of file statistics.h.

Referenced by statext_dependencies_build(), and statext_dependencies_deserialize().

◆ STATS_MAX_DIMENSIONS

#define STATS_MAX_DIMENSIONS   8 /* max number of attributes */

◆ STATS_MCV_MAGIC

#define STATS_MCV_MAGIC   0xE1A651C2 /* marks serialized bytea */

Definition at line 65 of file statistics.h.

Referenced by statext_mcv_build(), and statext_mcv_deserialize().

◆ STATS_MCV_TYPE_BASIC

#define STATS_MCV_TYPE_BASIC   1 /* basic MCV list type */

Definition at line 66 of file statistics.h.

Referenced by statext_mcv_build(), and statext_mcv_deserialize().

◆ STATS_MCVLIST_MAX_ITEMS

#define STATS_MCVLIST_MAX_ITEMS   10000

Definition at line 69 of file statistics.h.

Referenced by mcv_get_match_bitmap(), and statext_mcv_deserialize().

◆ STATS_NDISTINCT_MAGIC

#define STATS_NDISTINCT_MAGIC   0xA352BFA4 /* struct identifier */

◆ STATS_NDISTINCT_TYPE_BASIC

#define STATS_NDISTINCT_TYPE_BASIC   1 /* struct version */

Typedef Documentation

◆ MCVItem

typedef struct MCVItem MCVItem

◆ MCVList

typedef struct MCVList MCVList

◆ MVDependencies

◆ MVDependency

typedef struct MVDependency MVDependency

◆ MVNDistinct

typedef struct MVNDistinct MVNDistinct

◆ MVNDistinctItem

Function Documentation

◆ BuildRelationExtStatistics()

void BuildRelationExtStatistics ( Relation  onerel,
double  totalrows,
int  numrows,
HeapTuple rows,
int  natts,
VacAttrStats **  vacattrstats 
)

Definition at line 88 of file extended_stats.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, bms_num_members(), StatExtEntry::columns, CurrentMemoryContext, ereport, errcode(), errmsg(), errtable(), fetch_statentries_for_relation(), get_namespace_name(), IsAutoVacuumWorkerProcess(), lfirst, lfirst_int, list_length(), lookup_var_attr_stats(), MemoryContextDelete(), MemoryContextSwitchTo(), StatExtEntry::name, NIL, pgstat_progress_update_multi_param(), pgstat_progress_update_param(), PROGRESS_ANALYZE_EXT_STATS_COMPUTED, PROGRESS_ANALYZE_EXT_STATS_TOTAL, PROGRESS_ANALYZE_PHASE, PROGRESS_ANALYZE_PHASE_COMPUTE_EXT_STATS, RelationData::rd_rel, RelationGetRelationName, RelationGetRelid, RowExclusiveLock, StatExtEntry::schema, stat, statext_compute_stattarget(), statext_dependencies_build(), statext_mcv_build(), statext_ndistinct_build(), statext_store(), StatExtEntry::statOid, STATS_MAX_DIMENSIONS, StatExtEntry::stattarget, table_close(), table_open(), StatExtEntry::types, val, and WARNING.

Referenced by do_analyze_rel().

91 {
92  Relation pg_stext;
93  ListCell *lc;
94  List *stats;
95  MemoryContext cxt;
96  MemoryContext oldcxt;
97  int64 ext_cnt;
98 
100  "BuildRelationExtStatistics",
102  oldcxt = MemoryContextSwitchTo(cxt);
103 
104  pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
105  stats = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel));
106 
107  /* report this phase */
108  if (stats != NIL)
109  {
110  const int index[] = {
113  };
114  const int64 val[] = {
116  list_length(stats)
117  };
118 
119  pgstat_progress_update_multi_param(2, index, val);
120  }
121 
122  ext_cnt = 0;
123  foreach(lc, stats)
124  {
126  MVNDistinct *ndistinct = NULL;
127  MVDependencies *dependencies = NULL;
128  MCVList *mcv = NULL;
129  VacAttrStats **stats;
130  ListCell *lc2;
131  int stattarget;
132 
133  /*
134  * Check if we can build these stats based on the column analyzed. If
135  * not, report this fact (except in autovacuum) and move on.
136  */
137  stats = lookup_var_attr_stats(onerel, stat->columns,
138  natts, vacattrstats);
139  if (!stats)
140  {
143  (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
144  errmsg("statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"",
145  stat->schema, stat->name,
146  get_namespace_name(onerel->rd_rel->relnamespace),
147  RelationGetRelationName(onerel)),
148  errtable(onerel)));
149  continue;
150  }
151 
152  /* check allowed number of dimensions */
153  Assert(bms_num_members(stat->columns) >= 2 &&
155 
156  /* compute statistics target for this statistics */
157  stattarget = statext_compute_stattarget(stat->stattarget,
158  bms_num_members(stat->columns),
159  stats);
160 
161  /*
162  * Don't rebuild statistics objects with statistics target set to 0 (we
163  * just leave the existing values around, just like we do for regular
164  * per-column statistics).
165  */
166  if (stattarget == 0)
167  continue;
168 
169  /* compute statistic of each requested type */
170  foreach(lc2, stat->types)
171  {
172  char t = (char) lfirst_int(lc2);
173 
174  if (t == STATS_EXT_NDISTINCT)
175  ndistinct = statext_ndistinct_build(totalrows, numrows, rows,
176  stat->columns, stats);
177  else if (t == STATS_EXT_DEPENDENCIES)
178  dependencies = statext_dependencies_build(numrows, rows,
179  stat->columns, stats);
180  else if (t == STATS_EXT_MCV)
181  mcv = statext_mcv_build(numrows, rows, stat->columns, stats,
182  totalrows, stattarget);
183  }
184 
185  /* store the statistics in the catalog */
186  statext_store(stat->statOid, ndistinct, dependencies, mcv, stats);
187 
188  /* for reporting progress */
190  ++ext_cnt);
191  }
192 
193  table_close(pg_stext, RowExclusiveLock);
194 
195  MemoryContextSwitchTo(oldcxt);
196  MemoryContextDelete(cxt);
197 }
#define NIL
Definition: pg_list.h:65
MCVList * statext_mcv_build(int numrows, HeapTuple *rows, Bitmapset *attrs, VacAttrStats **stats, double totalrows, int stattarget)
Definition: mcv.c:183
#define PROGRESS_ANALYZE_EXT_STATS_COMPUTED
Definition: progress.h:42
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
#define PROGRESS_ANALYZE_PHASE
Definition: progress.h:38
void pgstat_progress_update_param(int index, int64 val)
Definition: pgstat.c:3213
static int statext_compute_stattarget(int stattarget, int natts, VacAttrStats **stats)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:608
static List * fetch_statentries_for_relation(Relation pg_statext, Oid relid)
Form_pg_class rd_rel
Definition: rel.h:84
Bitmapset * columns
Definition: type.h:89
#define lfirst_int(lc)
Definition: pg_list.h:191
#define PROGRESS_ANALYZE_EXT_STATS_TOTAL
Definition: progress.h:41
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3094
#define RowExclusiveLock
Definition: lockdefs.h:38
#define RelationGetRelationName(relation)
Definition: rel.h:462
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3278
#define ereport(elevel, rest)
Definition: elog.h:141
#define WARNING
Definition: elog.h:40
#define stat(a, b)
Definition: win32_port.h:255
MVDependencies * statext_dependencies_build(int numrows, HeapTuple *rows, Bitmapset *attrs, VacAttrStats **stats)
Definition: dependencies.c:357
MVNDistinct * statext_ndistinct_build(double totalrows, int numrows, HeapTuple *rows, Bitmapset *attrs, VacAttrStats **stats)
Definition: mvdistinct.c:86
#define PROGRESS_ANALYZE_PHASE_COMPUTE_EXT_STATS
Definition: progress.h:51
#define Assert(condition)
Definition: c.h:728
#define lfirst(lc)
Definition: pg_list.h:190
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
Definition: pgstat.c:3235
static int list_length(const List *l)
Definition: pg_list.h:169
static void statext_store(Oid relid, MVNDistinct *ndistinct, MVDependencies *dependencies, MCVList *mcv, VacAttrStats **stats)
#define STATS_MAX_DIMENSIONS
Definition: statistics.h:19
int errmsg(const char *fmt,...)
Definition: elog.c:822
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
int errtable(Relation rel)
Definition: relcache.c:5204
static VacAttrStats ** lookup_var_attr_stats(Relation rel, Bitmapset *attrs, int nvacatts, VacAttrStats **vacatts)
#define RelationGetRelid(relation)
Definition: rel.h:428
long val
Definition: informix.c:664

◆ choose_best_statistics()

StatisticExtInfo* choose_best_statistics ( List stats,
char  requiredkind,
Bitmapset **  clause_attnums,
int  nclauses 
)

Definition at line 882 of file extended_stats.c.

References bms_add_members(), bms_free(), bms_is_subset(), bms_num_members(), i, StatisticExtInfo::keys, StatisticExtInfo::kind, lfirst, and STATS_MAX_DIMENSIONS.

Referenced by statext_mcv_clauselist_selectivity().

884 {
885  ListCell *lc;
886  StatisticExtInfo *best_match = NULL;
887  int best_num_matched = 2; /* goal #1: maximize */
888  int best_match_keys = (STATS_MAX_DIMENSIONS + 1); /* goal #2: minimize */
889 
890  foreach(lc, stats)
891  {
892  int i;
893  StatisticExtInfo *info = (StatisticExtInfo *) lfirst(lc);
894  Bitmapset *matched = NULL;
895  int num_matched;
896  int numkeys;
897 
898  /* skip statistics that are not of the correct type */
899  if (info->kind != requiredkind)
900  continue;
901 
902  /*
903  * Collect attributes in remaining (unestimated) clauses fully covered
904  * by this statistic object.
905  */
906  for (i = 0; i < nclauses; i++)
907  {
908  /* ignore incompatible/estimated clauses */
909  if (!clause_attnums[i])
910  continue;
911 
912  /* ignore clauses that are not covered by this object */
913  if (!bms_is_subset(clause_attnums[i], info->keys))
914  continue;
915 
916  matched = bms_add_members(matched, clause_attnums[i]);
917  }
918 
919  num_matched = bms_num_members(matched);
920  bms_free(matched);
921 
922  /*
923  * save the actual number of keys in the stats so that we can choose
924  * the narrowest stats with the most matching keys.
925  */
926  numkeys = bms_num_members(info->keys);
927 
928  /*
929  * Use this object when it increases the number of matched clauses or
930  * when it matches the same number of attributes but these stats have
931  * fewer keys than any previous match.
932  */
933  if (num_matched > best_num_matched ||
934  (num_matched == best_num_matched && numkeys < best_match_keys))
935  {
936  best_match = info;
937  best_num_matched = num_matched;
938  best_match_keys = numkeys;
939  }
940  }
941 
942  return best_match;
943 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
#define lfirst(lc)
Definition: pg_list.h:190
Bitmapset * keys
Definition: pathnodes.h:887
#define STATS_MAX_DIMENSIONS
Definition: statistics.h:19
int i
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:793

◆ ComputeExtStatisticsRows()

int ComputeExtStatisticsRows ( Relation  onerel,
int  natts,
VacAttrStats **  stats 
)

Definition at line 213 of file extended_stats.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, bms_num_members(), StatExtEntry::columns, CurrentMemoryContext, fetch_statentries_for_relation(), lfirst, lookup_var_attr_stats(), MemoryContextDelete(), MemoryContextSwitchTo(), RelationGetRelid, RowExclusiveLock, stat, statext_compute_stattarget(), StatExtEntry::stattarget, table_close(), and table_open().

Referenced by do_analyze_rel().

215 {
216  Relation pg_stext;
217  ListCell *lc;
218  List *lstats;
219  MemoryContext cxt;
220  MemoryContext oldcxt;
221  int result = 0;
222 
224  "ComputeExtStatisticsRows",
226  oldcxt = MemoryContextSwitchTo(cxt);
227 
228  pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
229  lstats = fetch_statentries_for_relation(pg_stext, RelationGetRelid(onerel));
230 
231  foreach(lc, lstats)
232  {
234  int stattarget = stat->stattarget;
235  VacAttrStats **stats;
236  int nattrs = bms_num_members(stat->columns);
237 
238  /*
239  * Check if we can build this statistics object based on the columns
240  * analyzed. If not, ignore it (don't report anything, we'll do that
241  * during the actual build BuildRelationExtStatistics).
242  */
243  stats = lookup_var_attr_stats(onerel, stat->columns,
244  natts, vacattrstats);
245 
246  if (!stats)
247  continue;
248 
249  /*
250  * Compute statistics target, based on what's set for the statistic
251  * object itself, and for its attributes.
252  */
253  stattarget = statext_compute_stattarget(stat->stattarget,
254  nattrs, stats);
255 
256  /* Use the largest value for all statistics objects. */
257  if (stattarget > result)
258  result = stattarget;
259  }
260 
261  table_close(pg_stext, RowExclusiveLock);
262 
263  MemoryContextSwitchTo(oldcxt);
264  MemoryContextDelete(cxt);
265 
266  /* compute sample size based on the statistics target */
267  return (300 * result);
268 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
#define AllocSetContextCreate
Definition: memutils.h:170
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
static int statext_compute_stattarget(int stattarget, int natts, VacAttrStats **stats)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static List * fetch_statentries_for_relation(Relation pg_statext, Oid relid)
Bitmapset * columns
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
#define RowExclusiveLock
Definition: lockdefs.h:38
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
#define stat(a, b)
Definition: win32_port.h:255
#define lfirst(lc)
Definition: pg_list.h:190
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
static VacAttrStats ** lookup_var_attr_stats(Relation rel, Bitmapset *attrs, int nvacatts, VacAttrStats **vacatts)
#define RelationGetRelid(relation)
Definition: rel.h:428

◆ dependencies_clauselist_selectivity()

Selectivity dependencies_clauselist_selectivity ( PlannerInfo root,
List clauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo,
RelOptInfo rel,
Bitmapset **  estimatedclauses 
)

Definition at line 944 of file dependencies.c.

References attnum, bms_add_member(), bms_del_member(), bms_free(), bms_intersect(), bms_is_member(), bms_make_singleton(), bms_num_members(), bms_singleton_member(), clause_selectivity(), MVDependency::degree, DependencyGeneratorData::dependencies, dependency_implies_attribute(), dependency_is_compatible_clause(), find_strongest_dependency(), has_stats_of_kind(), i, StatisticExtInfo::keys, StatisticExtInfo::kind, lfirst, list_length(), DependencyGeneratorData::ndependencies, palloc(), pfree(), RelOptInfo::relid, s1, s2, stat, statext_dependencies_load(), RelOptInfo::statlist, and StatisticExtInfo::statOid.

Referenced by statext_clauselist_selectivity().

951 {
952  Selectivity s1 = 1.0;
953  ListCell *l;
954  Bitmapset *clauses_attnums = NULL;
955  Bitmapset **list_attnums;
956  int listidx;
957  MVDependencies **dependencies = NULL;
958  int ndependencies = 0;
959  int i;
960 
961  /* check if there's any stats that might be useful for us. */
962  if (!has_stats_of_kind(rel->statlist, STATS_EXT_DEPENDENCIES))
963  return 1.0;
964 
965  list_attnums = (Bitmapset **) palloc(sizeof(Bitmapset *) *
966  list_length(clauses));
967 
968  /*
969  * Pre-process the clauses list to extract the attnums seen in each item.
970  * We need to determine if there's any clauses which will be useful for
971  * dependency selectivity estimations. Along the way we'll record all of
972  * the attnums for each clause in a list which we'll reference later so we
973  * don't need to repeat the same work again. We'll also keep track of all
974  * attnums seen.
975  *
976  * We also skip clauses that we already estimated using different types of
977  * statistics (we treat them as incompatible).
978  */
979  listidx = 0;
980  foreach(l, clauses)
981  {
982  Node *clause = (Node *) lfirst(l);
984 
985  if (!bms_is_member(listidx, *estimatedclauses) &&
986  dependency_is_compatible_clause(clause, rel->relid, &attnum))
987  {
988  list_attnums[listidx] = bms_make_singleton(attnum);
989  clauses_attnums = bms_add_member(clauses_attnums, attnum);
990  }
991  else
992  list_attnums[listidx] = NULL;
993 
994  listidx++;
995  }
996 
997  /*
998  * If there's not at least two distinct attnums then reject the whole list
999  * of clauses. We must return 1.0 so the calling function's selectivity is
1000  * unaffected.
1001  */
1002  if (bms_num_members(clauses_attnums) < 2)
1003  {
1004  pfree(list_attnums);
1005  return 1.0;
1006  }
1007 
1008  /*
1009  * Load all functional dependencies matching at least two parameters. We
1010  * can simply consider all dependencies at once, without having to search
1011  * for the best statistics object.
1012  *
1013  * To not waste cycles and memory, we deserialize dependencies only for
1014  * statistics that match at least two attributes. The array is allocated
1015  * with the assumption that all objects match - we could grow the array
1016  * to make it just the right size, but it's likely wasteful anyway thanks
1017  * to moving the freed chunks to freelists etc.
1018  */
1019  ndependencies = 0;
1020  dependencies = (MVDependencies **) palloc(sizeof(MVDependencies *) *
1021  list_length(rel->statlist));
1022 
1023  foreach(l,rel->statlist)
1024  {
1026  Bitmapset *matched;
1027  int num_matched;
1028 
1029  /* skip statistics that are not of the correct type */
1030  if (stat->kind != STATS_EXT_DEPENDENCIES)
1031  continue;
1032 
1033  matched = bms_intersect(clauses_attnums, stat->keys);
1034  num_matched = bms_num_members(matched);
1035  bms_free(matched);
1036 
1037  /* skip objects matching fewer than two attributes from clauses */
1038  if (num_matched < 2)
1039  continue;
1040 
1041  dependencies[ndependencies++]
1043  }
1044 
1045  /* if no matching stats could be found then we've nothing to do */
1046  if (!ndependencies)
1047  {
1048  pfree(list_attnums);
1049  return 1.0;
1050  }
1051 
1052  /*
1053  * Apply the dependencies recursively, starting with the widest/strongest
1054  * ones, and proceeding to the smaller/weaker ones. At the end of each
1055  * round we factor in the selectivity of clauses on the implied attribute,
1056  * and remove the clauses from the list.
1057  */
1058  while (true)
1059  {
1060  Selectivity s2 = 1.0;
1061  MVDependency *dependency;
1062 
1063  /* the widest/strongest dependency, fully matched by clauses */
1064  dependency = find_strongest_dependency(dependencies, ndependencies,
1065  clauses_attnums);
1066 
1067  /* if no suitable dependency was found, we're done */
1068  if (!dependency)
1069  break;
1070 
1071  /*
1072  * We found an applicable dependency, so find all the clauses on the
1073  * implied attribute - with dependency (a,b => c) we look for clauses
1074  * on 'c'.
1075  */
1076  listidx = -1;
1077  foreach(l, clauses)
1078  {
1079  Node *clause;
1081 
1082  listidx++;
1083 
1084  /*
1085  * Skip incompatible clauses, and ones we've already estimated on.
1086  */
1087  if (!list_attnums[listidx])
1088  continue;
1089 
1090  /*
1091  * We expect the bitmaps ton contain a single attribute number.
1092  */
1093  attnum = bms_singleton_member(list_attnums[listidx]);
1094 
1095  /*
1096  * Technically we could find more than one clause for a given
1097  * attnum. Since these clauses must be equality clauses, we choose
1098  * to only take the selectivity estimate from the final clause in
1099  * the list for this attnum. If the attnum happens to be compared
1100  * to a different Const in another clause then no rows will match
1101  * anyway. If it happens to be compared to the same Const, then
1102  * ignoring the additional clause is just the thing to do.
1103  */
1104  if (dependency_implies_attribute(dependency, attnum))
1105  {
1106  clause = (Node *) lfirst(l);
1107 
1108  s2 = clause_selectivity(root, clause, varRelid, jointype,
1109  sjinfo);
1110 
1111  /* mark this one as done, so we don't touch it again. */
1112  *estimatedclauses = bms_add_member(*estimatedclauses, listidx);
1113 
1114  /*
1115  * Mark that we've got and used the dependency on this clause.
1116  * We'll want to ignore this when looking for the next
1117  * strongest dependency above.
1118  */
1119  clauses_attnums = bms_del_member(clauses_attnums, attnum);
1120  }
1121  }
1122 
1123  /*
1124  * Now factor in the selectivity for all the "implied" clauses into
1125  * the final one, using this formula:
1126  *
1127  * P(a,b) = P(a) * (f + (1-f) * P(b))
1128  *
1129  * where 'f' is the degree of validity of the dependency.
1130  */
1131  s1 *= (dependency->degree + (1 - dependency->degree) * s2);
1132  }
1133 
1134  /* free deserialized functional dependencies (and then the array) */
1135  for (i = 0; i < ndependencies; i++)
1136  pfree(dependencies[i]);
1137 
1138  pfree(dependencies);
1139  pfree(list_attnums);
1140 
1141  return s1;
1142 }
List * statlist
Definition: pathnodes.h:681
MVDependencies * statext_dependencies_load(Oid mvoid)
Definition: dependencies.c:634
Definition: nodes.h:525
double Selectivity
Definition: nodes.h:658
void pfree(void *pointer)
Definition: mcxt.c:1056
char * s1
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
Selectivity clause_selectivity(PlannerInfo *root, Node *clause, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo)
Definition: clausesel.c:600
Index relid
Definition: pathnodes.h:671
static bool dependency_implies_attribute(MVDependency *dependency, AttrNumber attnum)
Definition: dependencies.c:621
#define stat(a, b)
Definition: win32_port.h:255
static MVDependency * find_strongest_dependency(MVDependencies **dependencies, int ndependencies, Bitmapset *attnums)
Definition: dependencies.c:865
char * s2
int bms_singleton_member(const Bitmapset *a)
Definition: bitmapset.c:577
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:259
int16 attnum
Definition: pg_attribute.h:79
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
#define lfirst(lc)
Definition: pg_list.h:190
double degree
Definition: statistics.h:51
static int list_length(const List *l)
Definition: pg_list.h:169
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
Bitmapset * keys
Definition: pathnodes.h:887
void * palloc(Size size)
Definition: mcxt.c:949
int i
int l
Definition: api.h:16
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:773
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
bool has_stats_of_kind(List *stats, char requiredkind)
int16 AttrNumber
Definition: attnum.h:21
static bool dependency_is_compatible_clause(Node *clause, Index relid, AttrNumber *attnum)
Definition: dependencies.c:754

◆ has_stats_of_kind()

bool has_stats_of_kind ( List stats,
char  requiredkind 
)

Definition at line 848 of file extended_stats.c.

References StatisticExtInfo::kind, lfirst, and stat.

Referenced by dependencies_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

849 {
850  ListCell *l;
851 
852  foreach(l, stats)
853  {
855 
856  if (stat->kind == requiredkind)
857  return true;
858  }
859 
860  return false;
861 }
#define stat(a, b)
Definition: win32_port.h:255
#define lfirst(lc)
Definition: pg_list.h:190
int l
Definition: api.h:16

◆ statext_clauselist_selectivity()

Selectivity statext_clauselist_selectivity ( PlannerInfo root,
List clauses,
int  varRelid,
JoinType  jointype,
SpecialJoinInfo sjinfo,
RelOptInfo rel,
Bitmapset **  estimatedclauses 
)

Definition at line 1355 of file extended_stats.c.

References dependencies_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

Referenced by clauselist_selectivity().

1358 {
1359  Selectivity sel;
1360 
1361  /* First, try estimating clauses using a multivariate MCV list. */
1362  sel = statext_mcv_clauselist_selectivity(root, clauses, varRelid, jointype,
1363  sjinfo, rel, estimatedclauses);
1364 
1365  /*
1366  * Then, apply functional dependencies on the remaining clauses by calling
1367  * dependencies_clauselist_selectivity. Pass 'estimatedclauses' so the
1368  * function can properly skip clauses already estimated above.
1369  *
1370  * The reasoning for applying dependencies last is that the more complex
1371  * stats can track more complex correlations between the attributes, and
1372  * so may be considered more reliable.
1373  *
1374  * For example, MCV list can give us an exact selectivity for values in
1375  * two columns, while functional dependencies can only provide information
1376  * about the overall strength of the dependency.
1377  */
1378  sel *= dependencies_clauselist_selectivity(root, clauses, varRelid,
1379  jointype, sjinfo, rel,
1380  estimatedclauses);
1381 
1382  return sel;
1383 }
Selectivity dependencies_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
Definition: dependencies.c:944
double Selectivity
Definition: nodes.h:658
static Selectivity statext_mcv_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)

◆ statext_dependencies_load()

MVDependencies* statext_dependencies_load ( Oid  mvoid)

Definition at line 634 of file dependencies.c.

References DatumGetByteaPP, elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), statext_dependencies_deserialize(), STATEXTDATASTXOID, and SysCacheGetAttr().

Referenced by dependencies_clauselist_selectivity().

635 {
636  MVDependencies *result;
637  bool isnull;
638  Datum deps;
639  HeapTuple htup;
640 
642  if (!HeapTupleIsValid(htup))
643  elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
644 
645  deps = SysCacheGetAttr(STATEXTDATASTXOID, htup,
646  Anum_pg_statistic_ext_data_stxddependencies, &isnull);
647  if (isnull)
648  elog(ERROR,
649  "requested statistic kind \"%c\" is not yet built for statistics object %u",
650  STATS_EXT_DEPENDENCIES, mvoid);
651 
653 
654  ReleaseSysCache(htup);
655 
656  return result;
657 }
#define DatumGetByteaPP(X)
Definition: fmgr.h:285
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228
MVDependencies * statext_dependencies_deserialize(bytea *data)
Definition: dependencies.c:501

◆ statext_is_kind_built()

bool statext_is_kind_built ( HeapTuple  htup,
char  kind 
)

Definition at line 333 of file extended_stats.c.

References attnum, elog, ERROR, and heap_attisnull().

Referenced by get_relation_statistics(), and UpdateStatisticsForTypeChange().

334 {
336 
337  switch (type)
338  {
339  case STATS_EXT_NDISTINCT:
340  attnum = Anum_pg_statistic_ext_data_stxdndistinct;
341  break;
342 
343  case STATS_EXT_DEPENDENCIES:
344  attnum = Anum_pg_statistic_ext_data_stxddependencies;
345  break;
346 
347  case STATS_EXT_MCV:
348  attnum = Anum_pg_statistic_ext_data_stxdmcv;
349  break;
350 
351  default:
352  elog(ERROR, "unexpected statistics type requested: %d", type);
353  }
354 
355  return !heap_attisnull(htup, attnum, NULL);
356 }
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition: heaptuple.c:359
#define ERROR
Definition: elog.h:43
int16 attnum
Definition: pg_attribute.h:79
#define elog(elevel,...)
Definition: elog.h:228
int16 AttrNumber
Definition: attnum.h:21

◆ statext_mcv_load()

MCVList* statext_mcv_load ( Oid  mvoid)

Definition at line 557 of file mcv.c.

References DatumGetByteaP, elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), statext_mcv_deserialize(), STATEXTDATASTXOID, and SysCacheGetAttr().

Referenced by mcv_clauselist_selectivity().

558 {
559  MCVList *result;
560  bool isnull;
561  Datum mcvlist;
563 
564  if (!HeapTupleIsValid(htup))
565  elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
566 
567  mcvlist = SysCacheGetAttr(STATEXTDATASTXOID, htup,
568  Anum_pg_statistic_ext_data_stxdmcv, &isnull);
569 
570  if (isnull)
571  elog(ERROR,
572  "requested statistic kind \"%c\" is not yet built for statistics object %u",
573  STATS_EXT_DEPENDENCIES, mvoid);
574 
575  result = statext_mcv_deserialize(DatumGetByteaP(mcvlist));
576 
577  ReleaseSysCache(htup);
578 
579  return result;
580 }
MCVList * statext_mcv_deserialize(bytea *data)
Definition: mcv.c:992
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
#define DatumGetByteaP(X)
Definition: fmgr.h:325
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228

◆ statext_ndistinct_load()

MVNDistinct* statext_ndistinct_load ( Oid  mvoid)

Definition at line 141 of file mvdistinct.c.

References DatumGetByteaPP, elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1(), statext_ndistinct_deserialize(), STATEXTDATASTXOID, and SysCacheGetAttr().

Referenced by estimate_multivariate_ndistinct().

142 {
143  MVNDistinct *result;
144  bool isnull;
145  Datum ndist;
146  HeapTuple htup;
147 
149  if (!HeapTupleIsValid(htup))
150  elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
151 
152  ndist = SysCacheGetAttr(STATEXTDATASTXOID, htup,
153  Anum_pg_statistic_ext_data_stxdndistinct, &isnull);
154  if (isnull)
155  elog(ERROR,
156  "requested statistic kind \"%c\" is not yet built for statistics object %u",
157  STATS_EXT_NDISTINCT, mvoid);
158 
160 
161  ReleaseSysCache(htup);
162 
163  return result;
164 }
MVNDistinct * statext_ndistinct_deserialize(bytea *data)
Definition: mvdistinct.c:249
#define DatumGetByteaPP(X)
Definition: fmgr.h:285
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define elog(elevel,...)
Definition: elog.h:228