summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/analyze.c18
-rw-r--r--src/backend/statistics/dependencies.c10
-rw-r--r--src/backend/utils/adt/selfuncs.c20
-rw-r--r--src/test/regress/expected/stats_ext.out19
-rw-r--r--src/test/regress/sql/stats_ext.sql10
5 files changed, 65 insertions, 12 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 37b77e28cb9..26169808bee 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -529,6 +529,7 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params,
{
MemoryContext col_context,
old_context;
+ bool build_ext_stats;
col_context = AllocSetContextCreate(anl_context,
"Analyze Column",
@@ -590,12 +591,27 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params,
}
/*
+ * Should we build extended statistics for this relation?
+ *
+ * The extended statistics catalog does not include an inheritance
+ * flag, so we can't store statistics built both with and without
+ * data from child relations. We can store just one set of statistics
+ * per relation. For plain relations that's fine, but for inheritance
+ * trees we have to pick whether to store statistics for just the
+ * one relation or the whole tree. For plain inheritance we store
+ * the (!inh) version, mostly for backwards compatibility reasons.
+ * For partitioned tables that's pointless (the non-leaf tables are
+ * always empty), so we store stats representing the whole tree.
+ */
+ build_ext_stats = (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) ? inh : (!inh);
+
+ /*
* Build extended statistics (if there are any).
*
* For now we only build extended statistics on individual relations,
* not for relations representing inheritance trees.
*/
- if (!inh)
+ if (build_ext_stats)
BuildRelationExtStatistics(onerel, totalrows, numrows, rows,
attr_cnt, vacattrstats);
}
diff --git a/src/backend/statistics/dependencies.c b/src/backend/statistics/dependencies.c
index 9c7e7d9bfde..2ed80dce3c2 100644
--- a/src/backend/statistics/dependencies.c
+++ b/src/backend/statistics/dependencies.c
@@ -15,6 +15,7 @@
#include "access/htup_details.h"
#include "access/sysattr.h"
+#include "catalog/pg_class.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_statistic_ext.h"
#include "lib/stringinfo.h"
@@ -968,10 +969,13 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
*estimatedclauses = NULL;
/*
- * When dealing with inheritance trees, ignore extended stats (which were
- * built without data from child rels, and thus do not represent them).
+ * When dealing with regular inheritance trees, ignore extended stats
+ * (which were built without data from child rels, and thus do not
+ * represent them). For partitioned tables data there's no data in the
+ * non-leaf relations, so we build stats only for the inheritance tree.
+ * So for partitioned tables we do consider extended stats.
*/
- if (rte->inh)
+ if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
return 1.0;
/* check if there's any stats that might be useful for us. */
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index af247043f45..962bf075eea 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -3749,19 +3749,23 @@ estimate_multivariate_ndistinct(PlannerInfo *root, RelOptInfo *rel,
Oid statOid = InvalidOid;
MVNDistinct *stats;
Bitmapset *matched = NULL;
- RangeTblEntry *rte = planner_rt_fetch(rel->relid, root);
-
- /*
- * When dealing with inheritance trees, ignore extended stats (which were
- * built without data from child rels, and thus do not represent them).
- */
- if (rte->inh)
- return false;
+ RangeTblEntry *rte;
/* bail out immediately if the table has no extended statistics */
if (!rel->statlist)
return false;
+ /*
+ * When dealing with regular inheritance trees, ignore extended stats
+ * (which were built without data from child rels, and thus do not
+ * represent them). For partitioned tables data there's no data in the
+ * non-leaf relations, so we build stats only for the inheritance tree.
+ * So for partitioned tables we do consider extended stats.
+ */
+ rte = planner_rt_fetch(rel->relid, root);
+ if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
+ return false;
+
/* Determine the attnums we're looking for */
foreach(lc, *varinfos)
{
diff --git a/src/test/regress/expected/stats_ext.out b/src/test/regress/expected/stats_ext.out
index 66e770ab45a..620ffa2a5b5 100644
--- a/src/test/regress/expected/stats_ext.out
+++ b/src/test/regress/expected/stats_ext.out
@@ -172,6 +172,25 @@ SELECT * FROM check_estimated_rows('SELECT a, b FROM stxdinh* WHERE a = 0 AND b
(1 row)
DROP TABLE stxdinh, stxdinh1, stxdinh2;
+-- Ensure inherited stats ARE applied to inherited query in partitioned table
+CREATE TABLE stxdinp(i int, a int, b int) PARTITION BY RANGE (i);
+CREATE TABLE stxdinp1 PARTITION OF stxdinp FOR VALUES FROM (1) TO (100);
+INSERT INTO stxdinp SELECT 1, a/100, a/100 FROM generate_series(1, 999) a;
+CREATE STATISTICS stxdinp ON a, b FROM stxdinp;
+VACUUM ANALYZE stxdinp; -- partitions are processed recursively
+SELECT 1 FROM pg_statistic_ext WHERE stxrelid = 'stxdinp'::regclass;
+ ?column?
+----------
+ 1
+(1 row)
+
+SELECT * FROM check_estimated_rows('SELECT a, b FROM stxdinp GROUP BY 1, 2');
+ estimated | actual
+-----------+--------
+ 10 | 10
+(1 row)
+
+DROP TABLE stxdinp;
-- Verify supported object types for extended statistics
CREATE schema tststats;
CREATE TABLE tststats.t (a int, b int, c text);
diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql
index 8ef6d56c3ee..ffea1ac01ef 100644
--- a/src/test/regress/sql/stats_ext.sql
+++ b/src/test/regress/sql/stats_ext.sql
@@ -121,6 +121,16 @@ SELECT * FROM check_estimated_rows('SELECT a, b FROM stxdinh* GROUP BY 1, 2');
SELECT * FROM check_estimated_rows('SELECT a, b FROM stxdinh* WHERE a = 0 AND b = 0');
DROP TABLE stxdinh, stxdinh1, stxdinh2;
+-- Ensure inherited stats ARE applied to inherited query in partitioned table
+CREATE TABLE stxdinp(i int, a int, b int) PARTITION BY RANGE (i);
+CREATE TABLE stxdinp1 PARTITION OF stxdinp FOR VALUES FROM (1) TO (100);
+INSERT INTO stxdinp SELECT 1, a/100, a/100 FROM generate_series(1, 999) a;
+CREATE STATISTICS stxdinp ON a, b FROM stxdinp;
+VACUUM ANALYZE stxdinp; -- partitions are processed recursively
+SELECT 1 FROM pg_statistic_ext WHERE stxrelid = 'stxdinp'::regclass;
+SELECT * FROM check_estimated_rows('SELECT a, b FROM stxdinp GROUP BY 1, 2');
+DROP TABLE stxdinp;
+
-- Verify supported object types for extended statistics
CREATE schema tststats;