PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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   MAX_STATISTICS_TARGET
 

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, bool inh)
 
MVDependenciesstatext_dependencies_load (Oid mvoid, bool inh)
 
MCVListstatext_mcv_load (Oid mvoid, bool inh)
 
void BuildRelationExtStatistics (Relation onerel, bool inh, double totalrows, int numrows, HeapTuple *rows, int natts, VacAttrStats **vacattrstats)
 
int ComputeExtStatisticsRows (Relation onerel, int natts, VacAttrStats **vacattrstats)
 
bool statext_is_kind_built (HeapTuple htup, char type)
 
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 is_or)
 
bool has_stats_of_kind (List *stats, char requiredkind)
 
StatisticExtInfochoose_best_statistics (List *stats, char requiredkind, bool inh, Bitmapset **clause_attnums, List **clause_exprs, int nclauses)
 
HeapTuple statext_expressions_load (Oid stxoid, bool inh, int idx)
 

Macro Definition Documentation

◆ STATS_DEPS_MAGIC

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

Definition at line 43 of file statistics.h.

◆ STATS_DEPS_TYPE_BASIC

#define STATS_DEPS_TYPE_BASIC   1 /* basic dependencies type */

Definition at line 44 of file statistics.h.

◆ STATS_MAX_DIMENSIONS

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

Definition at line 19 of file statistics.h.

◆ STATS_MCV_MAGIC

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

Definition at line 66 of file statistics.h.

◆ STATS_MCV_TYPE_BASIC

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

Definition at line 67 of file statistics.h.

◆ STATS_MCVLIST_MAX_ITEMS

#define STATS_MCVLIST_MAX_ITEMS   MAX_STATISTICS_TARGET

Definition at line 70 of file statistics.h.

◆ STATS_NDISTINCT_MAGIC

#define STATS_NDISTINCT_MAGIC   0xA352BFA4 /* struct identifier */

Definition at line 22 of file statistics.h.

◆ STATS_NDISTINCT_TYPE_BASIC

#define STATS_NDISTINCT_TYPE_BASIC   1 /* struct version */

Definition at line 23 of file statistics.h.

Typedef Documentation

◆ MCVItem

◆ MCVList

◆ MVDependencies

◆ MVDependency

◆ MVNDistinct

◆ MVNDistinctItem

Function Documentation

◆ BuildRelationExtStatistics()

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

Definition at line 111 of file extended_stats.c.

114{
116 ListCell *lc;
118 MemoryContext cxt;
121
122 /* Do nothing if there are no columns to analyze. */
123 if (!natts)
124 return;
125
126 /* the list of stats has to be allocated outside the memory context */
129
130 /* memory context for building each statistics object */
132 "BuildRelationExtStatistics",
135
136 /* report this phase */
137 if (statslist != NIL)
138 {
139 const int index[] = {
142 };
143 const int64 val[] = {
146 };
147
149 }
150
151 ext_cnt = 0;
152 foreach(lc, statslist)
153 {
155 MVNDistinct *ndistinct = NULL;
156 MVDependencies *dependencies = NULL;
157 MCVList *mcv = NULL;
158 Datum exprstats = (Datum) 0;
159 VacAttrStats **stats;
160 ListCell *lc2;
161 int stattarget;
163
164 /*
165 * Check if we can build these stats based on the column analyzed. If
166 * not, report this fact (except in autovacuum) and move on.
167 */
168 stats = lookup_var_attr_stats(stat->columns, stat->exprs,
169 natts, vacattrstats);
170 if (!stats)
171 {
175 errmsg("statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"",
176 stat->schema, stat->name,
177 get_namespace_name(onerel->rd_rel->relnamespace),
179 errtable(onerel)));
180 continue;
181 }
182
183 /* compute statistics target for this statistics object */
184 stattarget = statext_compute_stattarget(stat->stattarget,
185 bms_num_members(stat->columns),
186 stats);
187
188 /*
189 * Don't rebuild statistics objects with statistics target set to 0
190 * (we just leave the existing values around, just like we do for
191 * regular per-column statistics).
192 */
193 if (stattarget == 0)
194 continue;
195
196 /* evaluate expressions (if the statistics object has any) */
197 data = make_build_data(onerel, stat, numrows, rows, stats, stattarget);
198
199 /* compute statistic of each requested type */
200 foreach(lc2, stat->types)
201 {
202 char t = (char) lfirst_int(lc2);
203
204 if (t == STATS_EXT_NDISTINCT)
206 else if (t == STATS_EXT_DEPENDENCIES)
207 dependencies = statext_dependencies_build(data);
208 else if (t == STATS_EXT_MCV)
209 mcv = statext_mcv_build(data, totalrows, stattarget);
210 else if (t == STATS_EXT_EXPRESSIONS)
211 {
213 int nexprs;
214
215 /* should not happen, thanks to checks when defining stats */
216 if (!stat->exprs)
217 elog(ERROR, "requested expression stats, but there are no expressions");
218
219 exprdata = build_expr_data(stat->exprs, stattarget);
220 nexprs = list_length(stat->exprs);
221
222 compute_expr_stats(onerel, exprdata, nexprs, rows, numrows);
223
225 }
226 }
227
228 /* store the statistics in the catalog */
229 statext_store(stat->statOid, inh,
230 ndistinct, dependencies, mcv, exprstats, stats);
231
232 /* for reporting progress */
234 ++ext_cnt);
235
236 /* free the data used for building this statistics object */
238 }
239
242
244
246}
void pgstat_progress_update_param(int index, int64 val)
void pgstat_progress_update_multi_param(int nparam, const int *index, const int64 *val)
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:750
int64_t int64
Definition c.h:543
MVDependencies * statext_dependencies_build(StatsBuildData *data)
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define WARNING
Definition elog.h:36
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
static AnlExprData * build_expr_data(List *exprs, int stattarget)
static VacAttrStats ** lookup_var_attr_stats(Bitmapset *attrs, List *exprs, int nvacatts, VacAttrStats **vacatts)
static StatsBuildData * make_build_data(Relation rel, StatExtEntry *stat, int numrows, HeapTuple *rows, VacAttrStats **stats, int stattarget)
static List * fetch_statentries_for_relation(Relation pg_statext, Oid relid)
static void statext_store(Oid statOid, bool inh, MVNDistinct *ndistinct, MVDependencies *dependencies, MCVList *mcv, Datum exprs, VacAttrStats **stats)
static int statext_compute_stattarget(int stattarget, int nattrs, VacAttrStats **stats)
static void compute_expr_stats(Relation onerel, AnlExprData *exprdata, int nexprs, HeapTuple *rows, int numrows)
static Datum serialize_expr_stats(AnlExprData *exprdata, int nexprs)
long val
Definition informix.c:689
void list_free(List *list)
Definition list.c:1546
#define RowExclusiveLock
Definition lockdefs.h:38
char * get_namespace_name(Oid nspid)
Definition lsyscache.c:3516
MCVList * statext_mcv_build(StatsBuildData *data, double totalrows, int stattarget)
Definition mcv.c:178
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define AmAutoVacuumWorkerProcess()
Definition miscadmin.h:383
MVNDistinct * statext_ndistinct_build(double totalrows, StatsBuildData *data)
Definition mvdistinct.c:85
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
const void * data
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define lfirst_int(lc)
Definition pg_list.h:173
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
#define PROGRESS_ANALYZE_EXT_STATS_COMPUTED
Definition progress.h:58
#define PROGRESS_ANALYZE_PHASE
Definition progress.h:54
#define PROGRESS_ANALYZE_PHASE_COMPUTE_EXT_STATS
Definition progress.h:69
#define PROGRESS_ANALYZE_EXT_STATS_TOTAL
Definition progress.h:57
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetRelationName(relation)
Definition rel.h:548
int errtable(Relation rel)
Definition relcache.c:6044
Definition pg_list.h:54
Definition type.h:96
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, AmAutoVacuumWorkerProcess, bms_num_members(), build_expr_data(), compute_expr_stats(), CurrentMemoryContext, data, elog, ereport, errcode(), errmsg(), ERROR, errtable(), fb(), fetch_statentries_for_relation(), get_namespace_name(), lfirst, lfirst_int, list_free(), list_length(), lookup_var_attr_stats(), make_build_data(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), 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, RelationGetRelationName, RelationGetRelid, RowExclusiveLock, serialize_expr_stats(), statext_compute_stattarget(), statext_dependencies_build(), statext_mcv_build(), statext_ndistinct_build(), statext_store(), table_close(), table_open(), val, and WARNING.

Referenced by do_analyze_rel().

◆ choose_best_statistics()

StatisticExtInfo * choose_best_statistics ( List stats,
char  requiredkind,
bool  inh,
Bitmapset **  clause_attnums,
List **  clause_exprs,
int  nclauses 
)
extern

Definition at line 1207 of file extended_stats.c.

1210{
1211 ListCell *lc;
1213 int best_num_matched = 2; /* goal #1: maximize */
1214 int best_match_keys = (STATS_MAX_DIMENSIONS + 1); /* goal #2: minimize */
1215
1216 foreach(lc, stats)
1217 {
1218 int i;
1222 int num_matched;
1223 int numkeys;
1224
1225 /* skip statistics that are not of the correct type */
1226 if (info->kind != requiredkind)
1227 continue;
1228
1229 /* skip statistics with mismatching inheritance flag */
1230 if (info->inherit != inh)
1231 continue;
1232
1233 /*
1234 * Collect attributes and expressions in remaining (unestimated)
1235 * clauses fully covered by this statistic object.
1236 *
1237 * We know already estimated clauses have both clause_attnums and
1238 * clause_exprs set to NULL. We leave the pointers NULL if already
1239 * estimated, or we reset them to NULL after estimating the clause.
1240 */
1241 for (i = 0; i < nclauses; i++)
1242 {
1244
1245 /* ignore incompatible/estimated clauses */
1246 if (!clause_attnums[i] && !clause_exprs[i])
1247 continue;
1248
1249 /* ignore clauses that are not covered by this object */
1250 if (!bms_is_subset(clause_attnums[i], info->keys) ||
1252 continue;
1253
1254 /* record attnums and indexes of expressions covered */
1257 }
1258
1260
1263
1264 /*
1265 * save the actual number of keys in the stats so that we can choose
1266 * the narrowest stats with the most matching keys.
1267 */
1268 numkeys = bms_num_members(info->keys) + list_length(info->exprs);
1269
1270 /*
1271 * Use this object when it increases the number of matched attributes
1272 * and expressions or when it matches the same number of attributes
1273 * and expressions but these stats have fewer keys than any previous
1274 * match.
1275 */
1278 {
1279 best_match = info;
1281 best_match_keys = numkeys;
1282 }
1283 }
1284
1285 return best_match;
1286}
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:412
void bms_free(Bitmapset *a)
Definition bitmapset.c:239
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:916
static bool stat_covers_expressions(StatisticExtInfo *stat, List *exprs, Bitmapset **expr_idxs)
int i
Definition isn.c:77
#define STATS_MAX_DIMENSIONS
Definition statistics.h:19
Bitmapset * keys
Definition pathnodes.h:1431

References bms_add_members(), bms_free(), bms_is_subset(), bms_num_members(), StatisticExtInfo::exprs, fb(), i, StatisticExtInfo::inherit, StatisticExtInfo::keys, StatisticExtInfo::kind, lfirst, list_length(), stat_covers_expressions(), and STATS_MAX_DIMENSIONS.

Referenced by statext_mcv_clauselist_selectivity().

◆ ComputeExtStatisticsRows()

int ComputeExtStatisticsRows ( Relation  onerel,
int  natts,
VacAttrStats **  vacattrstats 
)
extern

Definition at line 262 of file extended_stats.c.

264{
266 ListCell *lc;
267 List *lstats;
268 MemoryContext cxt;
270 int result = 0;
271
272 /* If there are no columns to analyze, just return 0. */
273 if (!natts)
274 return 0;
275
277 "ComputeExtStatisticsRows",
280
283
284 foreach(lc, lstats)
285 {
287 int stattarget;
288 VacAttrStats **stats;
289 int nattrs = bms_num_members(stat->columns);
290
291 /*
292 * Check if we can build this statistics object based on the columns
293 * analyzed. If not, ignore it (don't report anything, we'll do that
294 * during the actual build BuildRelationExtStatistics).
295 */
296 stats = lookup_var_attr_stats(stat->columns, stat->exprs,
297 natts, vacattrstats);
298
299 if (!stats)
300 continue;
301
302 /*
303 * Compute statistics target, based on what's set for the statistic
304 * object itself, and for its attributes.
305 */
306 stattarget = statext_compute_stattarget(stat->stattarget,
307 nattrs, stats);
308
309 /* Use the largest value for all statistics objects. */
310 if (stattarget > result)
311 result = stattarget;
312 }
313
315
318
319 /* compute sample size based on the statistics target */
320 return (300 * result);
321}

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, bms_num_members(), CurrentMemoryContext, fb(), fetch_statentries_for_relation(), lfirst, lookup_var_attr_stats(), MemoryContextDelete(), MemoryContextSwitchTo(), RelationGetRelid, RowExclusiveLock, statext_compute_stattarget(), table_close(), and table_open().

Referenced by do_analyze_rel().

◆ dependencies_clauselist_selectivity()

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

Definition at line 1354 of file dependencies.c.

1361{
1362 Selectivity s1 = 1.0;
1363 ListCell *l;
1366 int listidx;
1369 int total_ndeps;
1370 MVDependency **dependencies;
1371 int ndependencies;
1372 int i;
1375
1376 /* unique expressions */
1378 int unique_exprs_cnt;
1379
1380 /* check if there's any stats that might be useful for us. */
1382 return 1.0;
1383
1385
1386 /*
1387 * We allocate space as if every clause was a unique expression, although
1388 * that's probably overkill. Some will be simple column references that
1389 * we'll translate to attnums, and there might be duplicates. But it's
1390 * easier and cheaper to just do one allocation than repalloc later.
1391 */
1393 unique_exprs_cnt = 0;
1394
1395 /*
1396 * Pre-process the clauses list to extract the attnums seen in each item.
1397 * We need to determine if there's any clauses which will be useful for
1398 * dependency selectivity estimations. Along the way we'll record all of
1399 * the attnums for each clause in a list which we'll reference later so we
1400 * don't need to repeat the same work again. We'll also keep track of all
1401 * attnums seen.
1402 *
1403 * We also skip clauses that we already estimated using different types of
1404 * statistics (we treat them as incompatible).
1405 *
1406 * To handle expressions, we assign them negative attnums, as if it was a
1407 * system attribute (this is fine, as we only allow extended stats on user
1408 * attributes). And then we offset everything by the number of
1409 * expressions, so that we can store the values in a bitmapset.
1410 */
1411 listidx = 0;
1412 foreach(l, clauses)
1413 {
1414 Node *clause = (Node *) lfirst(l);
1416 Node *expr = NULL;
1417
1418 /* ignore clause by default */
1420
1422 {
1423 /*
1424 * If it's a simple column reference, just extract the attnum. If
1425 * it's an expression, assign a negative attnum as if it was a
1426 * system attribute.
1427 */
1428 if (dependency_is_compatible_clause(clause, rel->relid, &attnum))
1429 {
1431 }
1432 else if (dependency_is_compatible_expression(clause, rel->relid,
1433 rel->statlist,
1434 &expr))
1435 {
1436 /* special attnum assigned to this expression */
1438
1439 Assert(expr != NULL);
1440
1441 /* If the expression is duplicate, use the same attnum. */
1442 for (i = 0; i < unique_exprs_cnt; i++)
1443 {
1444 if (equal(unique_exprs[i], expr))
1445 {
1446 /* negative attribute number to expression */
1447 attnum = -(i + 1);
1448 break;
1449 }
1450 }
1451
1452 /* not found in the list, so add it */
1454 {
1456
1457 /* after incrementing the value, to get -1, -2, ... */
1459 }
1460
1461 /* remember which attnum was assigned to this clause */
1463 }
1464 }
1465
1466 listidx++;
1467 }
1468
1469 Assert(listidx == list_length(clauses));
1470
1471 /*
1472 * How much we need to offset the attnums? If there are no expressions,
1473 * then no offset is needed. Otherwise we need to offset enough for the
1474 * lowest value (-unique_exprs_cnt) to become 1.
1475 */
1476 if (unique_exprs_cnt > 0)
1478 else
1479 attnum_offset = 0;
1480
1481 /*
1482 * Now that we know how many expressions there are, we can offset the
1483 * values just enough to build the bitmapset.
1484 */
1485 for (i = 0; i < list_length(clauses); i++)
1486 {
1488
1489 /* ignore incompatible or already estimated clauses */
1491 continue;
1492
1493 /* make sure the attnum is in the expected range */
1496
1497 /* make sure the attnum is positive (valid AttrNumber) */
1499
1500 /*
1501 * Either it's a regular attribute, or it's an expression, in which
1502 * case we must not have seen it before (expressions are unique).
1503 *
1504 * XXX Check whether it's a regular attribute has to be done using the
1505 * original attnum, while the second check has to use the value with
1506 * an offset.
1507 */
1510
1511 /*
1512 * Remember the offset attnum, both for attributes and expressions.
1513 * We'll pass list_attnums to clauselist_apply_dependencies, which
1514 * uses it to identify clauses in a bitmap. We could also pass the
1515 * offset, but this is more convenient.
1516 */
1518
1520 }
1521
1522 /*
1523 * If there's not at least two distinct attnums and expressions, then
1524 * reject the whole list of clauses. We must return 1.0 so the calling
1525 * function's selectivity is unaffected.
1526 */
1528 {
1531 return 1.0;
1532 }
1533
1534 /*
1535 * Load all functional dependencies matching at least two parameters. We
1536 * can simply consider all dependencies at once, without having to search
1537 * for the best statistics object.
1538 *
1539 * To not waste cycles and memory, we deserialize dependencies only for
1540 * statistics that match at least two attributes. The array is allocated
1541 * with the assumption that all objects match - we could grow the array to
1542 * make it just the right size, but it's likely wasteful anyway thanks to
1543 * moving the freed chunks to freelists etc.
1544 */
1547 total_ndeps = 0;
1548
1549 foreach(l, rel->statlist)
1550 {
1552 int nmatched;
1553 int nexprs;
1554 int k;
1555 MVDependencies *deps;
1556
1557 /* skip statistics that are not of the correct type */
1558 if (stat->kind != STATS_EXT_DEPENDENCIES)
1559 continue;
1560
1561 /* skip statistics with mismatching stxdinherit value */
1562 if (stat->inherit != rte->inh)
1563 continue;
1564
1565 /*
1566 * Count matching attributes - we have to undo the attnum offsets. The
1567 * input attribute numbers are not offset (expressions are not
1568 * included in stat->keys, so it's not necessary). But we need to
1569 * offset it before checking against clauses_attnums.
1570 */
1571 nmatched = 0;
1572 k = -1;
1573 while ((k = bms_next_member(stat->keys, k)) >= 0)
1574 {
1576
1577 /* skip expressions */
1579 continue;
1580
1581 /* apply the same offset as above */
1583
1585 nmatched++;
1586 }
1587
1588 /* count matching expressions */
1589 nexprs = 0;
1590 for (i = 0; i < unique_exprs_cnt; i++)
1591 {
1592 ListCell *lc;
1593
1594 foreach(lc, stat->exprs)
1595 {
1596 Node *stat_expr = (Node *) lfirst(lc);
1597
1598 /* try to match it */
1600 nexprs++;
1601 }
1602 }
1603
1604 /*
1605 * Skip objects matching fewer than two attributes/expressions from
1606 * clauses.
1607 */
1608 if (nmatched + nexprs < 2)
1609 continue;
1610
1611 deps = statext_dependencies_load(stat->statOid, rte->inh);
1612
1613 /*
1614 * The expressions may be represented by different attnums in the
1615 * stats, we need to remap them to be consistent with the clauses.
1616 * That will make the later steps (e.g. picking the strongest item and
1617 * so on) much simpler and cheaper, because it won't need to care
1618 * about the offset at all.
1619 *
1620 * When we're at it, we can ignore dependencies that are not fully
1621 * matched by clauses (i.e. referencing attributes or expressions that
1622 * are not in the clauses).
1623 *
1624 * We have to do this for all statistics, as long as there are any
1625 * expressions - we need to shift the attnums in all dependencies.
1626 *
1627 * XXX Maybe we should do this always, because it also eliminates some
1628 * of the dependencies early. It might be cheaper than having to walk
1629 * the longer list in find_strongest_dependency later, especially as
1630 * we need to do that repeatedly?
1631 *
1632 * XXX We have to do this even when there are no expressions in
1633 * clauses, otherwise find_strongest_dependency may fail for stats
1634 * with expressions (due to lookup of negative value in bitmap). So we
1635 * need to at least filter out those dependencies. Maybe we could do
1636 * it in a cheaper way (if there are no expr clauses, we can just
1637 * discard all negative attnums without any lookups).
1638 */
1639 if (unique_exprs_cnt > 0 || stat->exprs != NIL)
1640 {
1641 int ndeps = 0;
1642
1643 for (i = 0; i < deps->ndeps; i++)
1644 {
1645 bool skip = false;
1646 MVDependency *dep = deps->deps[i];
1647 int j;
1648
1649 for (j = 0; j < dep->nattributes; j++)
1650 {
1651 int idx;
1652 Node *expr;
1655
1656 /* undo the per-statistics offset */
1657 attnum = dep->attributes[j];
1658
1659 /*
1660 * For regular attributes we can simply check if it
1661 * matches any clause. If there's no matching clause, we
1662 * can just ignore it. We need to offset the attnum
1663 * though.
1664 */
1666 {
1667 dep->attributes[j] = attnum + attnum_offset;
1668
1669 if (!bms_is_member(dep->attributes[j], clauses_attnums))
1670 {
1671 skip = true;
1672 break;
1673 }
1674
1675 continue;
1676 }
1677
1678 /*
1679 * the attnum should be a valid system attnum (-1, -2,
1680 * ...)
1681 */
1683
1684 /*
1685 * For expressions, we need to do two translations. First
1686 * we have to translate the negative attnum to index in
1687 * the list of expressions (in the statistics object).
1688 * Then we need to see if there's a matching clause. The
1689 * index of the unique expression determines the attnum
1690 * (and we offset it).
1691 */
1692 idx = -(1 + attnum);
1693
1694 /* Is the expression index is valid? */
1695 Assert((idx >= 0) && (idx < list_length(stat->exprs)));
1696
1697 expr = (Node *) list_nth(stat->exprs, idx);
1698
1699 /* try to find the expression in the unique list */
1700 for (int m = 0; m < unique_exprs_cnt; m++)
1701 {
1702 /*
1703 * found a matching unique expression, use the attnum
1704 * (derived from index of the unique expression)
1705 */
1706 if (equal(unique_exprs[m], expr))
1707 {
1708 unique_attnum = -(m + 1) + attnum_offset;
1709 break;
1710 }
1711 }
1712
1713 /*
1714 * Found no matching expression, so we can simply skip
1715 * this dependency, because there's no chance it will be
1716 * fully covered.
1717 */
1719 {
1720 skip = true;
1721 break;
1722 }
1723
1724 /* otherwise remap it to the new attnum */
1725 dep->attributes[j] = unique_attnum;
1726 }
1727
1728 /* if found a matching dependency, keep it */
1729 if (!skip)
1730 {
1731 /* maybe we've skipped something earlier, so move it */
1732 if (ndeps != i)
1733 deps->deps[ndeps] = deps->deps[i];
1734
1735 ndeps++;
1736 }
1737 }
1738
1739 deps->ndeps = ndeps;
1740 }
1741
1742 /*
1743 * It's possible we've removed all dependencies, in which case we
1744 * don't bother adding it to the list.
1745 */
1746 if (deps->ndeps > 0)
1747 {
1749 total_ndeps += deps->ndeps;
1751 }
1752 }
1753
1754 /* if no matching stats could be found then we've nothing to do */
1755 if (nfunc_dependencies == 0)
1756 {
1761 return 1.0;
1762 }
1763
1764 /*
1765 * Work out which dependencies we can apply, starting with the
1766 * widest/strongest ones, and proceeding to smaller/weaker ones.
1767 */
1768 dependencies = palloc_array(MVDependency *, total_ndeps);
1769 ndependencies = 0;
1770
1771 while (true)
1772 {
1773 MVDependency *dependency;
1775
1776 /* the widest/strongest dependency, fully matched by clauses */
1780 if (!dependency)
1781 break;
1782
1783 dependencies[ndependencies++] = dependency;
1784
1785 /* Ignore dependencies using this implied attribute in later loops */
1786 attnum = dependency->attributes[dependency->nattributes - 1];
1788 }
1789
1790 /*
1791 * If we found applicable dependencies, use them to estimate all
1792 * compatible clauses on attributes that they refer to.
1793 */
1794 if (ndependencies != 0)
1795 s1 = clauselist_apply_dependencies(root, clauses, varRelid, jointype,
1796 sjinfo, dependencies, ndependencies,
1798
1799 /* free deserialized functional dependencies (and then the array) */
1800 for (i = 0; i < nfunc_dependencies; i++)
1802
1803 pfree(dependencies);
1808
1809 return s1;
1810}
Datum idx(PG_FUNCTION_ARGS)
Definition _int_op.c:262
int16 AttrNumber
Definition attnum.h:21
#define AttributeNumberIsValid(attributeNumber)
Definition attnum.h:34
#define AttrNumberIsForUserDefinedAttr(attributeNumber)
Definition attnum.h:41
#define InvalidAttrNumber
Definition attnum.h:23
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1305
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:867
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:814
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:780
@ BMS_MULTIPLE
Definition bitmapset.h:73
#define Assert(condition)
Definition c.h:873
MVDependencies * statext_dependencies_load(Oid mvoid, bool inh)
static bool dependency_is_compatible_expression(Node *clause, Index relid, List *statlist, Node **expr)
static bool dependency_is_compatible_clause(Node *clause, Index relid, AttrNumber *attnum)
static Selectivity clauselist_apply_dependencies(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, MVDependency **dependencies, int ndependencies, AttrNumber *list_attnums, Bitmapset **estimatedclauses)
static MVDependency * find_strongest_dependency(MVDependencies **dependencies, int ndependencies, Bitmapset *attnums)
bool equal(const void *a, const void *b)
Definition equalfuncs.c:223
bool has_stats_of_kind(List *stats, char requiredkind)
#define palloc_array(type, count)
Definition fe_memutils.h:76
#define MaxHeapAttributeNumber
int j
Definition isn.c:78
void pfree(void *pointer)
Definition mcxt.c:1616
double Selectivity
Definition nodes.h:260
#define planner_rt_fetch(rti, root)
Definition pathnodes.h:610
int16 attnum
static const struct exclude_list_item skip[]
static void * list_nth(const List *list, int n)
Definition pg_list.h:299
char * s1
tree ctl root
Definition radixtree.h:1857
MVDependency * deps[FLEXIBLE_ARRAY_MEMBER]
Definition statistics.h:62
AttrNumber nattributes
Definition statistics.h:53
AttrNumber attributes[FLEXIBLE_ARRAY_MEMBER]
Definition statistics.h:54
Definition nodes.h:135
Index relid
Definition pathnodes.h:973
List * statlist
Definition pathnodes.h:997

References Assert, attnum, AttributeNumberIsValid, MVDependency::attributes, AttrNumberIsForUserDefinedAttr, bms_add_member(), bms_del_member(), bms_free(), bms_is_member(), bms_membership(), BMS_MULTIPLE, bms_next_member(), clauselist_apply_dependencies(), dependency_is_compatible_clause(), dependency_is_compatible_expression(), MVDependencies::deps, equal(), fb(), find_strongest_dependency(), has_stats_of_kind(), i, idx(), InvalidAttrNumber, j, lfirst, list_length(), list_nth(), MaxHeapAttributeNumber, MVDependency::nattributes, MVDependencies::ndeps, NIL, palloc_array, pfree(), planner_rt_fetch, RelOptInfo::relid, root, s1, skip, statext_dependencies_load(), and RelOptInfo::statlist.

Referenced by statext_clauselist_selectivity().

◆ has_stats_of_kind()

bool has_stats_of_kind ( List stats,
char  requiredkind 
)
extern

Definition at line 1116 of file extended_stats.c.

1117{
1118 ListCell *l;
1119
1120 foreach(l, stats)
1121 {
1123
1124 if (stat->kind == requiredkind)
1125 return true;
1126 }
1127
1128 return false;
1129}

References fb(), and lfirst.

Referenced by dependencies_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

◆ statext_clauselist_selectivity()

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

Definition at line 1981 of file extended_stats.c.

1985{
1987
1988 /* First, try estimating clauses using a multivariate MCV list. */
1989 sel = statext_mcv_clauselist_selectivity(root, clauses, varRelid, jointype,
1990 sjinfo, rel, estimatedclauses, is_or);
1991
1992 /*
1993 * Functional dependencies only work for clauses connected by AND, so for
1994 * OR clauses we're done.
1995 */
1996 if (is_or)
1997 return sel;
1998
1999 /*
2000 * Then, apply functional dependencies on the remaining clauses by calling
2001 * dependencies_clauselist_selectivity. Pass 'estimatedclauses' so the
2002 * function can properly skip clauses already estimated above.
2003 *
2004 * The reasoning for applying dependencies last is that the more complex
2005 * stats can track more complex correlations between the attributes, and
2006 * so may be considered more reliable.
2007 *
2008 * For example, MCV list can give us an exact selectivity for values in
2009 * two columns, while functional dependencies can only provide information
2010 * about the overall strength of the dependency.
2011 */
2012 sel *= dependencies_clauselist_selectivity(root, clauses, varRelid,
2013 jointype, sjinfo, rel,
2015
2016 return sel;
2017}
Selectivity dependencies_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses)
static Selectivity statext_mcv_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo, RelOptInfo *rel, Bitmapset **estimatedclauses, bool is_or)

References dependencies_clauselist_selectivity(), fb(), root, and statext_mcv_clauselist_selectivity().

Referenced by clauselist_selectivity_ext(), and clauselist_selectivity_or().

◆ statext_dependencies_load()

MVDependencies * statext_dependencies_load ( Oid  mvoid,
bool  inh 
)
extern

Definition at line 688 of file dependencies.c.

689{
690 MVDependencies *result;
691 bool isnull;
692 Datum deps;
693 HeapTuple htup;
694
697 BoolGetDatum(inh));
698 if (!HeapTupleIsValid(htup))
699 elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
700
703 if (isnull)
704 elog(ERROR,
705 "requested statistics kind \"%c\" is not yet built for statistics object %u",
707
709
710 ReleaseSysCache(htup);
711
712 return result;
713}
MVDependencies * statext_dependencies_deserialize(bytea *data)
#define DatumGetByteaPP(X)
Definition fmgr.h:292
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:595
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition syscache.c:230

References BoolGetDatum(), DatumGetByteaPP, elog, ERROR, fb(), HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache2(), statext_dependencies_deserialize(), and SysCacheGetAttr().

Referenced by dependencies_clauselist_selectivity().

◆ statext_expressions_load()

HeapTuple statext_expressions_load ( Oid  stxoid,
bool  inh,
int  idx 
)
extern

Definition at line 2401 of file extended_stats.c.

2402{
2403 bool isnull;
2404 Datum value;
2405 HeapTuple htup;
2407 HeapTupleHeader td;
2409 HeapTuple tup;
2410
2413 if (!HeapTupleIsValid(htup))
2414 elog(ERROR, "cache lookup failed for statistics object %u", stxoid);
2415
2418 if (isnull)
2419 elog(ERROR,
2420 "requested statistics kind \"%c\" is not yet built for statistics object %u",
2422
2424
2426
2427 td = DatumGetHeapTupleHeader(eah->dvalues[idx]);
2428
2429 /* Build a temporary HeapTuple control structure */
2431 ItemPointerSetInvalid(&(tmptup.t_self));
2432 tmptup.t_tableOid = InvalidOid;
2433 tmptup.t_data = td;
2434
2436
2437 ReleaseSysCache(htup);
2438
2439 return tup;
2440}
void deconstruct_expanded_array(ExpandedArrayHeader *eah)
ExpandedArrayHeader * DatumGetExpandedArray(Datum d)
#define DatumGetHeapTupleHeader(X)
Definition fmgr.h:296
HeapTuple heap_copytuple(HeapTuple tuple)
Definition heaptuple.c:778
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
static struct @172 value
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition itemptr.h:184
#define InvalidOid

References BoolGetDatum(), DatumGetExpandedArray(), DatumGetHeapTupleHeader, deconstruct_expanded_array(), elog, ERROR, fb(), heap_copytuple(), HeapTupleHeaderGetDatumLength(), HeapTupleIsValid, idx(), InvalidOid, ItemPointerSetInvalid(), ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache2(), SysCacheGetAttr(), and value.

Referenced by examine_variable().

◆ statext_is_kind_built()

bool statext_is_kind_built ( HeapTuple  htup,
char  type 
)
extern

Definition at line 386 of file extended_stats.c.

387{
389
390 switch (type)
391 {
394 break;
395
398 break;
399
400 case STATS_EXT_MCV:
402 break;
403
406 break;
407
408 default:
409 elog(ERROR, "unexpected statistics type requested: %d", type);
410 }
411
412 return !heap_attisnull(htup, attnum, NULL);
413}
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Definition heaptuple.c:456
const char * type

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

Referenced by get_relation_statistics_worker().

◆ statext_mcv_load()

MCVList * statext_mcv_load ( Oid  mvoid,
bool  inh 
)
extern

Definition at line 556 of file mcv.c.

557{
558 MCVList *result;
559 bool isnull;
563
564 if (!HeapTupleIsValid(htup))
565 elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
566
569
570 if (isnull)
571 elog(ERROR,
572 "requested statistics kind \"%c\" is not yet built for statistics object %u",
574
576
577 ReleaseSysCache(htup);
578
579 return result;
580}
#define DatumGetByteaP(X)
Definition fmgr.h:332
MCVList * statext_mcv_deserialize(bytea *data)
Definition mcv.c:994

References BoolGetDatum(), DatumGetByteaP, elog, ERROR, fb(), HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache2(), statext_mcv_deserialize(), and SysCacheGetAttr().

Referenced by mcv_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

◆ statext_ndistinct_load()

MVNDistinct * statext_ndistinct_load ( Oid  mvoid,
bool  inh 
)
extern

Definition at line 145 of file mvdistinct.c.

146{
147 MVNDistinct *result;
148 bool isnull;
149 Datum ndist;
150 HeapTuple htup;
151
154 if (!HeapTupleIsValid(htup))
155 elog(ERROR, "cache lookup failed for statistics object %u", mvoid);
156
159 if (isnull)
160 elog(ERROR,
161 "requested statistics kind \"%c\" is not yet built for statistics object %u",
163
165
166 ReleaseSysCache(htup);
167
168 return result;
169}
MVNDistinct * statext_ndistinct_deserialize(bytea *data)
Definition mvdistinct.c:247

References BoolGetDatum(), DatumGetByteaPP, elog, ERROR, fb(), HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), SearchSysCache2(), statext_ndistinct_deserialize(), and SysCacheGetAttr().

Referenced by estimate_multivariate_ndistinct().