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)
 
bool HasRelationExtStatistics (Relation onerel)
 
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 112 of file extended_stats.c.

115{
117 ListCell *lc;
119 MemoryContext cxt;
122
123 /* Do nothing if there are no columns to analyze. */
124 if (!natts)
125 return;
126
127 /* the list of stats has to be allocated outside the memory context */
130
131 /* memory context for building each statistics object */
133 "BuildRelationExtStatistics",
136
137 /* report this phase */
138 if (statslist != NIL)
139 {
140 const int index[] = {
143 };
144 const int64 val[] = {
147 };
148
150 }
151
152 ext_cnt = 0;
153 foreach(lc, statslist)
154 {
156 MVNDistinct *ndistinct = NULL;
157 MVDependencies *dependencies = NULL;
158 MCVList *mcv = NULL;
159 Datum exprstats = (Datum) 0;
160 VacAttrStats **stats;
161 ListCell *lc2;
162 int stattarget;
164
165 /*
166 * Check if we can build these stats based on the column analyzed. If
167 * not, report this fact (except in autovacuum) and move on.
168 */
169 stats = lookup_var_attr_stats(stat->columns, stat->exprs,
170 natts, vacattrstats);
171 if (!stats)
172 {
176 errmsg("statistics object \"%s.%s\" could not be computed for relation \"%s.%s\"",
177 stat->schema, stat->name,
178 get_namespace_name(onerel->rd_rel->relnamespace),
180 errtable(onerel)));
181 continue;
182 }
183
184 /* compute statistics target for this statistics object */
185 stattarget = statext_compute_stattarget(stat->stattarget,
186 bms_num_members(stat->columns),
187 stats);
188
189 /*
190 * Don't rebuild statistics objects with statistics target set to 0
191 * (we just leave the existing values around, just like we do for
192 * regular per-column statistics).
193 */
194 if (stattarget == 0)
195 continue;
196
197 /* evaluate expressions (if the statistics object has any) */
198 data = make_build_data(onerel, stat, numrows, rows, stats, stattarget);
199
200 /* compute statistic of each requested type */
201 foreach(lc2, stat->types)
202 {
203 char t = (char) lfirst_int(lc2);
204
205 if (t == STATS_EXT_NDISTINCT)
207 else if (t == STATS_EXT_DEPENDENCIES)
208 dependencies = statext_dependencies_build(data);
209 else if (t == STATS_EXT_MCV)
210 mcv = statext_mcv_build(data, totalrows, stattarget);
211 else if (t == STATS_EXT_EXPRESSIONS)
212 {
214 int nexprs;
215
216 /* should not happen, thanks to checks when defining stats */
217 if (!stat->exprs)
218 elog(ERROR, "requested expression stats, but there are no expressions");
219
220 exprdata = build_expr_data(stat->exprs, stattarget);
221 nexprs = list_length(stat->exprs);
222
223 compute_expr_stats(onerel, exprdata, nexprs, rows, numrows);
224
226 }
227 }
228
229 /* store the statistics in the catalog */
230 statext_store(stat->statOid, inh,
231 ndistinct, dependencies, mcv, exprstats, stats);
232
233 /* for reporting progress */
235 ++ext_cnt);
236
237 /* free the data used for building this statistics object */
239 }
240
243
245
247}
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:744
int64_t int64
Definition c.h:621
MVDependencies * statext_dependencies_build(StatsBuildData *data)
int errcode(int sqlerrcode)
Definition elog.c:874
#define WARNING
Definition elog.h:37
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
static AnlExprData * build_expr_data(List *exprs, int stattarget)
static VacAttrStats ** lookup_var_attr_stats(Bitmapset *attrs, List *exprs, int nvacatts, VacAttrStats **vacatts)
static List * fetch_statentries_for_relation(Relation pg_statext, Relation rel)
static StatsBuildData * make_build_data(Relation rel, StatExtEntry *stat, int numrows, HeapTuple *rows, VacAttrStats **stats, int stattarget)
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:3588
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:398
MVNDistinct * statext_ndistinct_build(double totalrows, StatsBuildData *data)
Definition mvdistinct.c:85
static char * errmsg
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 RelationGetRelationName(relation)
Definition rel.h:550
int errtable(Relation rel)
Definition relcache.c:6063
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, 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 1256 of file extended_stats.c.

1259{
1260 ListCell *lc;
1262 int best_num_matched = 2; /* goal #1: maximize */
1263 int best_match_keys = (STATS_MAX_DIMENSIONS + 1); /* goal #2: minimize */
1264
1265 foreach(lc, stats)
1266 {
1267 int i;
1271 int num_matched;
1272 int numkeys;
1273
1274 /* skip statistics that are not of the correct type */
1275 if (info->kind != requiredkind)
1276 continue;
1277
1278 /* skip statistics with mismatching inheritance flag */
1279 if (info->inherit != inh)
1280 continue;
1281
1282 /*
1283 * Collect attributes and expressions in remaining (unestimated)
1284 * clauses fully covered by this statistic object.
1285 *
1286 * We know already estimated clauses have both clause_attnums and
1287 * clause_exprs set to NULL. We leave the pointers NULL if already
1288 * estimated, or we reset them to NULL after estimating the clause.
1289 */
1290 for (i = 0; i < nclauses; i++)
1291 {
1293
1294 /* ignore incompatible/estimated clauses */
1295 if (!clause_attnums[i] && !clause_exprs[i])
1296 continue;
1297
1298 /* ignore clauses that are not covered by this object */
1299 if (!bms_is_subset(clause_attnums[i], info->keys) ||
1301 continue;
1302
1303 /* record attnums and indexes of expressions covered */
1306 }
1307
1309
1312
1313 /*
1314 * save the actual number of keys in the stats so that we can choose
1315 * the narrowest stats with the most matching keys.
1316 */
1317 numkeys = bms_num_members(info->keys) + list_length(info->exprs);
1318
1319 /*
1320 * Use this object when it increases the number of matched attributes
1321 * and expressions or when it matches the same number of attributes
1322 * and expressions but these stats have fewer keys than any previous
1323 * match.
1324 */
1327 {
1328 best_match = info;
1330 best_match_keys = numkeys;
1331 }
1332 }
1333
1334 return best_match;
1335}
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:901
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:1529

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 297 of file extended_stats.c.

299{
301 ListCell *lc;
302 List *lstats;
303 MemoryContext cxt;
305 int result = 0;
306
307 /* If there are no columns to analyze, just return 0. */
308 if (!natts)
309 return 0;
310
312 "ComputeExtStatisticsRows",
315
318
319 foreach(lc, lstats)
320 {
322 int stattarget;
323 VacAttrStats **stats;
324 int nattrs = bms_num_members(stat->columns);
325
326 /*
327 * Check if we can build this statistics object based on the columns
328 * analyzed. If not, ignore it (don't report anything, we'll do that
329 * during the actual build BuildRelationExtStatistics).
330 */
331 stats = lookup_var_attr_stats(stat->columns, stat->exprs,
332 natts, vacattrstats);
333
334 if (!stats)
335 continue;
336
337 /*
338 * Compute statistics target, based on what's set for the statistic
339 * object itself, and for its attributes.
340 */
341 stattarget = statext_compute_stattarget(stat->stattarget,
342 nattrs, stats);
343
344 /* Use the largest value for all statistics objects. */
345 if (stattarget > result)
346 result = stattarget;
347 }
348
350
353
354 /* compute sample size based on the statistics target */
355 return (300 * result);
356}
uint32 result

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, bms_num_members(), CurrentMemoryContext, fb(), fetch_statentries_for_relation(), lfirst, lookup_var_attr_stats(), MemoryContextDelete(), MemoryContextSwitchTo(), result, 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:1290
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:852
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:765
@ BMS_MULTIPLE
Definition bitmapset.h:73
#define Assert(condition)
Definition c.h:943
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:704
int16 attnum
static const struct exclude_list_item skip[]
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
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:1069
List * statlist
Definition pathnodes.h:1093

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 1165 of file extended_stats.c.

1166{
1167 ListCell *l;
1168
1169 foreach(l, stats)
1170 {
1172
1173 if (stat->kind == requiredkind)
1174 return true;
1175 }
1176
1177 return false;
1178}

References fb(), and lfirst.

Referenced by dependencies_clauselist_selectivity(), and statext_mcv_clauselist_selectivity().

◆ HasRelationExtStatistics()

bool HasRelationExtStatistics ( Relation  onerel)
extern

Definition at line 253 of file extended_stats.c.

254{
256 SysScanDesc scan;
258 bool found;
259
261
262 /*
263 * Prepare to scan pg_statistic_ext for entries having stxrelid = this
264 * rel.
265 */
270
272 NULL, 1, &skey);
273
274 found = HeapTupleIsValid(systable_getnext(scan));
275
276 systable_endscan(scan);
277
279
280 return found;
281}
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:612
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:523
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
#define RelationGetRelid(relation)
Definition rel.h:516
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition scankey.c:76
#define BTEqualStrategyNumber
Definition stratnum.h:31

References BTEqualStrategyNumber, fb(), HeapTupleIsValid, ObjectIdGetDatum(), RelationGetRelid, RowExclusiveLock, ScanKeyInit(), systable_beginscan(), systable_endscan(), systable_getnext(), table_close(), and table_open().

Referenced by postgresImportForeignStatistics().

◆ 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 2030 of file extended_stats.c.

2034{
2036
2037 /* First, try estimating clauses using a multivariate MCV list. */
2038 sel = statext_mcv_clauselist_selectivity(root, clauses, varRelid, jointype,
2039 sjinfo, rel, estimatedclauses, is_or);
2040
2041 /*
2042 * Functional dependencies only work for clauses connected by AND, so for
2043 * OR clauses we're done.
2044 */
2045 if (is_or)
2046 return sel;
2047
2048 /*
2049 * Then, apply functional dependencies on the remaining clauses by calling
2050 * dependencies_clauselist_selectivity. Pass 'estimatedclauses' so the
2051 * function can properly skip clauses already estimated above.
2052 *
2053 * The reasoning for applying dependencies last is that the more complex
2054 * stats can track more complex correlations between the attributes, and
2055 * so may be considered more reliable.
2056 *
2057 * For example, MCV list can give us an exact selectivity for values in
2058 * two columns, while functional dependencies can only provide information
2059 * about the overall strength of the dependency.
2060 */
2061 sel *= dependencies_clauselist_selectivity(root, clauses, varRelid,
2062 jointype, sjinfo, rel,
2064
2065 return sel;
2066}
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{
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
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
Datum SysCacheGetAttr(SysCacheIdentifier cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:596

References BoolGetDatum(), DatumGetByteaPP, elog, ERROR, fb(), HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), result, 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 2453 of file extended_stats.c.

2454{
2455 bool isnull;
2456 Datum value;
2457 HeapTuple htup;
2459 HeapTupleHeader td;
2461 HeapTuple tup;
2462
2465 if (!HeapTupleIsValid(htup))
2466 elog(ERROR, "cache lookup failed for statistics object %u", stxoid);
2467
2470 if (isnull)
2471 elog(ERROR,
2472 "requested statistics kind \"%c\" is not yet built for statistics object %u",
2474
2476
2478
2479 if (eah->dnulls && eah->dnulls[idx])
2480 {
2481 /* No data found for this expression, give up. */
2482 ReleaseSysCache(htup);
2483 return NULL;
2484 }
2485
2486 td = DatumGetHeapTupleHeader(eah->dvalues[idx]);
2487
2488 /* Build a temporary HeapTuple control structure */
2490 ItemPointerSetInvalid(&(tmptup.t_self));
2491 tmptup.t_tableOid = InvalidOid;
2492 tmptup.t_data = td;
2493
2495
2496 ReleaseSysCache(htup);
2497
2498 return tup;
2499}
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:686
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
static struct @177 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 421 of file extended_stats.c.

422{
424
425 switch (type)
426 {
429 break;
430
433 break;
434
435 case STATS_EXT_MCV:
437 break;
438
441 break;
442
443 default:
444 elog(ERROR, "unexpected statistics type requested: %d", type);
445 }
446
447 return !heap_attisnull(htup, attnum, NULL);
448}
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{
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(), result, 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{
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(), result, SearchSysCache2(), statext_ndistinct_deserialize(), and SysCacheGetAttr().

Referenced by estimate_multivariate_ndistinct().